0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-03-11 17:08:46 +00:00

Birdtest: Add bt_assert_fn_in_*

- Improved test output formating: aligned, colored [ OK ] / [FAIL]
- A failed assert will not interupt the whole test suite
- bt_assert_fn_in_* are macros for testing input and output from the some
  function
This commit is contained in:
Pavel Tvrdík 2015-04-13 10:52:21 +02:00
parent 947018a7ef
commit a84b9c62d1
10 changed files with 177 additions and 47 deletions

View File

@ -120,7 +120,7 @@ t_log2(void)
in_out_data[i].in = pow2(i+1);
in_out_data[i].out = i+1;
}
bt_check(u32_log2, in_out_data, "%u", "%u");
bt_assert_fn_in(u32_log2, in_out_data, "%u", "%u");
u32_log2(0);
@ -142,5 +142,5 @@ main(int argc, char *argv[])
bt_test_suite(t_masklen, "u32_masklen()");
bt_test_suite(t_log2, "u32_log2()");
return 0;
return bt_end();
}

View File

@ -150,7 +150,7 @@ main(int argc, char *argv[])
bt_test_suite(t_buffer_resize, "Init a small buffer and try overfill");
bt_test_suite(t_buffer_flush, "Fill and flush all elements");
return 0;
return bt_end();
}

View File

@ -94,7 +94,7 @@ main(int argc, char *argv[])
bt_test_suite(t_calculate, "Checksum of pseudo-random data");
bt_test_suite(t_verify, "Verification of pseudo-random data.");
return 0;
return bt_end();
}
/* Mockup */

View File

@ -72,6 +72,6 @@ main(int argc, char *argv[])
bt_test_suite(t_ev_run_list, "Schedule and run 3 events in right order.");
return 0;
return bt_end();
}

View File

@ -301,5 +301,5 @@ main(int argc, char *argv[])
//bt_test_case(t_walk_delsafe_remove2, "HASH_WALK_DELSAFE and HASH_REMOVE2. HASH_REMOVE2 is HASH_REMOVE and smart auto-resize function");
bt_test_suite(t_walk_filter, "HASH_WALK_FILTER");
return 0;
return bt_end();
}

View File

@ -181,5 +181,5 @@ main(int argc, char *argv[])
bt_test_suite(t_heap_delete, "Deleting");
bt_test_suite(t_heap_0, "Is a heap[0] really unused?");
return 0;
return bt_end();
}

View File

@ -62,9 +62,9 @@ t_ip4_pton(void)
},
};
bt_check(ip4_pton_, in_out_data, "%s", "0x%08X");
bt_assert_fn_in(ip4_pton_, in_out_data, "%s", "0x%08X");
return BT_SUCCESS;
return bt_test_case_success;
}
int
@ -74,6 +74,6 @@ main(int argc, char *argv[])
bt_test_suite(t_ip4_pton, "Converting IPv4 string to ip4_addr struct");
return 0;
return bt_end();
}

View File

@ -89,5 +89,5 @@ main(int argc, char *argv[])
bt_test_suite(t_md5, "Test Suite from RFC1321");
return 0;
return bt_end();
}

View File

@ -4,14 +4,16 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <unistd.h>
#include <execinfo.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/wait.h>
@ -28,6 +30,9 @@ int bt_verbose;
const char *bt_filename;
const char *bt_test_id;
int bt_success;
int bt_test_case_success;
int
bt_rand_num(void)
{
@ -40,10 +45,12 @@ bt_init(int argc, char *argv[])
{
int c;
bt_success = 1;
srandom(BT_RANDOM_SEED);
bt_verbose = 0;
bt_filename = argv[0];
bt_test_id = NULL;
while ((c = getopt(argc, argv, "lcftv")) >= 0)
switch (c)
@ -125,10 +132,12 @@ bt_test_suite5(int (*test_fn)(void), const char *test_id, const char *dsc, int f
return;
int result = 0;
bt_test_case_success = 1;
bt_test_id = test_id;
bt_note("Starting %s: %s", test_id, dsc);
if (bt_verbose >= BT_VERBOSE_DEBUG)
bt_log("Starting");
if (!forked)
{
@ -172,12 +181,42 @@ bt_test_suite5(int (*test_fn)(void), const char *test_id, const char *dsc, int f
bt_log("Core dumped");
}
if (result != BT_SUCCESS)
{
bt_log("Test case failed");
exit(result);
}
bt_note("OK");
bt_success &= (result == BT_SUCCESS ? 1 : 0);
bt_result((result == BT_SUCCESS ? BT_PROMPT_OK : BT_PROMPT_FAIL), "%s", bt_test_id);
bt_test_id = NULL;
}
static uint
get_num_terminal_cols(void)
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return w.ws_col;
}
void
bt_result(const char *to_right_align_msg, const char *to_left_align_msg, ...)
{
if (bt_verbose)
{
va_list argptr;
va_start(argptr, to_left_align_msg);
char msg_buf[BT_BUFFER_SIZE];
snprintf(msg_buf, sizeof(msg_buf), "%s: ", bt_filename);
vsnprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf), to_left_align_msg, argptr);
char fmt_buf[BT_BUFFER_SIZE];
uint line_len = strlen(msg_buf) + BT_PROMPT_OK_FAIL_LEN;
uint left_offset = (line_len / get_num_terminal_cols() + 1) * get_num_terminal_cols() - BT_PROMPT_OK_FAIL_LEN;
snprintf(fmt_buf, sizeof(fmt_buf), "%%-%us%%s\n", left_offset);
fprintf(stderr, fmt_buf, msg_buf, to_right_align_msg);
}
}
int
bt_end(void)
{
return !bt_success;
}

View File

@ -13,24 +13,41 @@
#include <string.h>
#include <errno.h>
extern int bt_success;
extern int bt_test_case_success;
extern int bt_verbose;
#define BT_VERBOSE_NOTHING 0
#define BT_VERBOSE_TEST_CASE 1
#define BT_VERBOSE_DEBUG 2
extern const char *bt_filename;
extern const char *bt_test_id;
void bt_init(int argc, char *argv[]);
int bt_end(void);
void bt_test_suite5(int (*fn)(void), const char *id, const char *dsc, int forked, int timeout);
int bt_rand_num(void);
void bt_result(const char *result, const char *msg, ...);
#define BT_SUCCESS 0
#define BT_FAILURE 1
#define BT_SUCCESS 1
#define BT_FAILURE 0
#define BT_DEFAULT_TIMEOUT 5
#define BT_DEFAULT_FORKING 1
#define BT_DEFAULT_TIMEOUT 5
#define BT_DEFAULT_FORKING 1
#define BT_RANDOM_SEED 982451653
#define BT_RANDOM_SEED 982451653
#define bt_test_case(fn,dsc) \
bt_test_case4(fn, dsc, BT_DEFAULT_FORKING, BT_DEFAULT_TIMEOUT)
#define BT_BUFFER_SIZE 1000
#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 "
#define bt_test_suite(fn,dsc) \
bt_test_suite4(fn, dsc, BT_DEFAULT_FORKING, BT_DEFAULT_TIMEOUT)
@ -39,13 +56,31 @@ int bt_rand_num(void);
bt_test_suite5(fn, #fn, dsc, f, t)
#define bt_log(format, ...) \
fprintf(stderr, "%s: " format "\n", bt_filename, ##__VA_ARGS__)
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)
#define bt_note(format, ...) \
do { if (bt_verbose) bt_log(format, ##__VA_ARGS__); } while (0)
#define bt_log_test_case(format, ...) \
do { if (bt_verbose >= BT_VERBOSE_TEST_CASE) bt_log(format, ##__VA_ARGS__); } while (0)
#define bt_debug(format, ...) \
do { if (bt_verbose > 1) printf(format, ##__VA_ARGS__); } while (0)
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)
#define bt_abort() \
bt_abort_msg("Aborted at %s:%d", __FILE__, __LINE__)
@ -56,23 +91,79 @@ int bt_rand_num(void);
#define bt_assert(test) \
bt_assert_msg(test, "Assertion (%s) failed at %s:%d", #test, __FILE__, __LINE__)
#define bt_assert_msg(test,format, ...) \
do { if (!(test)) bt_abort_msg(format, ##__VA_ARGS__); } while (0)
#define bt_assert_msg(test, format, ...) \
do { if (!(test)) { \
if (bt_verbose) bt_log(format, ##__VA_ARGS__); \
bt_success = bt_test_case_success = 0; \
} } while (0)
#define bt_syscall(test,format, ...) \
#define bt_syscall(test,format, ...) \
do { if (test) { bt_log(format ": %s", ##__VA_ARGS__, strerror(errno)); exit(3); } } while (0)
#define bt_check(fn, in_out, in_fmt, out_fmt) \
do \
{ \
unsigned int bt_i; \
for (bt_i = 0; bt_i < (sizeof(in_out)/sizeof(in_out[0])); bt_i++) \
{ \
if (fn(in_out[bt_i].in) == in_out[bt_i].out) \
bt_debug ("[ OK ] %s(" in_fmt ") got " out_fmt " \n", #fn, in_out[bt_i].in, fn(in_out[bt_i].in)); \
else \
bt_abort_msg("[FAIL] %s(" in_fmt ") got " out_fmt ", but was expected " out_fmt " \n", #fn, in_out[bt_i].in, fn(in_out[bt_i].in), in_out[bt_i].out); \
} \
} while(0)
#define bt_assert_fn_in(fn, in_out, in_fmt, out_fmt) \
do \
{ \
unsigned int i; \
for (i = 0; i < (sizeof(in_out)/sizeof(in_out[0])); i++) \
{ \
int single_test_case_success = fn(in_out[i].in) == in_out[i].out; \
bt_test_case_success &= single_test_case_success; \
if (single_test_case_success) \
bt_result_check_ok(BT_PROMPT_FN_GIVES(in_fmt) out_fmt, #fn, in_out[i].in, fn(in_out[i].in)); \
else \
bt_result_check_fail(BT_PROMPT_FN_GIVES(in_fmt) out_fmt BT_PROMPT_EXPECTING out_fmt, #fn, in_out[i].in, fn(in_out[i].in), in_out[i].out); \
} \
} while (0)
#define bt_assert_fn_in_out(fn, in_out, in_fmt, out_fmt) \
do \
{ \
unsigned int i; \
for (i = 0; i < (sizeof(in_out)/sizeof(in_out[0])); i++) \
{ \
fn(in_out[i].in, &in_out[i].fn_out); \
int single_test_case_success = !memcmp(&in_out[i].fn_out, &in_out[i].out, sizeof(in_out[i].out)); \
bt_test_case_success &= single_test_case_success; \
if (single_test_case_success) \
bt_result_check_ok (BT_PROMPT_FN_GIVES(in_fmt) out_fmt, #fn, in_out[i].in, in_out[i].fn_out); \
else \
bt_result_check_fail(BT_PROMPT_FN_GIVES(in_fmt) out_fmt BT_PROMPT_EXPECTING out_fmt, #fn, in_out[i].in, in_out[i].fn_out, in_out[i].out); \
} \
} while (0)
#define bt_strcat(buf, str, ...) snprintf(buf + strlen(buf), sizeof(buf), str, ##__VA_ARGS__)
#define bt_dump_struct(buf, data) \
do \
{ \
unsigned int bt_j; \
u32 *bt_pc = (u32*) data; \
bt_strcat(buf, "{"); \
for (bt_j = 0; bt_j < (sizeof(*data) / sizeof(typeof(*bt_pc))); bt_j++) \
bt_strcat(buf, "%s0x%08X", (bt_j ? ", " : ""), bt_pc[bt_j]); \
bt_strcat(buf, "}"); \
} while (0)
#define bt_assert_fn_in_out_struct(fn, in_out, in_fmt) \
do \
{ \
char bt_buf[BT_BUFFER_SIZE]; \
unsigned int i; \
for (i = 0; i < (sizeof(in_out)/sizeof(in_out[0])); i++) \
{ \
strcpy(bt_buf, ""); \
fn(in_out[i].in, &in_out[i].fn_out); \
int single_test_case_success = !memcmp(&in_out[i].fn_out, in_out[i].out, sizeof(in_out[i].out)); \
bt_test_case_success &= single_test_case_success; \
bt_strcat(bt_buf, BT_PROMPT_FN_GIVES(in_fmt), #fn, in_out[i].in); \
bt_dump_struct(bt_buf, &in_out[i].fn_out); \
if (!single_test_case_success) \
{ \
bt_strcat(bt_buf, BT_PROMPT_EXPECTING); \
bt_dump_struct(bt_buf, &in_out[i].out); \
} \
bt_result_check((single_test_case_success ? BT_PROMPT_OK : BT_PROMPT_FAIL), "%s", bt_buf); \
} \
} while (0)
#endif /* _BIRDTEST_H_ */