* 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>
const char *bt_filename;
const char *bt_test_id;
+int bt_success;
+int bt_test_case_success;
+
int
bt_rand_num(void)
{
{
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)
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)
{
bt_log("Core dumped");
}
- if (result != BT_SUCCESS)
+ 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)
{
- bt_log("Test case failed");
- exit(result);
- }
+ 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);
- bt_note("OK");
+ fprintf(stderr, fmt_buf, msg_buf, to_right_align_msg);
+ }
}
+int
+bt_end(void)
+{
+ return !bt_success;
+}
#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 1
+#define BT_FAILURE 0
-#define BT_SUCCESS 0
-#define BT_FAILURE 1
+#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_BUFFER_SIZE 1000
-#define bt_test_case(fn,dsc) \
- bt_test_case4(fn, dsc, BT_DEFAULT_FORKING, BT_DEFAULT_TIMEOUT)
+#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)
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__)
#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_ */