* Can be freely distributed and used under the terms of the GNU GPL.
*/
+#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include <time.h>
#include <unistd.h>
#include <sys/ioctl.h>
static const char *request;
static int list_tests;
static int do_core;
+static int do_die;
static int no_fork;
static int no_timeout;
static int is_terminal; /* Whether stdout is a live terminal or pipe redirect */
+volatile sig_atomic_t async_config_flag; /* Asynchronous reconfiguration/dump scheduled */
+volatile sig_atomic_t async_dump_flag;
+volatile sig_atomic_t async_shutdown_flag;
+
+
uint bt_verbose;
const char *bt_filename;
const char *bt_test_id;
int bt_suite_result; /* One suit result */
char bt_out_fmt_buf[1024]; /* Temporary memory buffer for output of testing function */
-long int
-bt_random(void)
-{
- /* Seeded in bt_init() */
- long int rand_low, rand_high;
+struct timespec bt_begin, bt_suite_begin, bt_suite_case_begin;
- rand_low = random();
- rand_high = random();
- return (rand_low & 0xffff) | ((rand_high & 0xffff) << 16);
-}
+u64 bt_random_state[] = {
+ 0x80241f302bd4d95d, 0xd10ba2e910f772b, 0xea188c9046f507c5, 0x4c4c581f04e6da05,
+ 0x53d9772877c1b647, 0xab8ce3eb466de6c5, 0xad02844c8a8e865f, 0xe8cc78080295065d
+};
void
bt_init(int argc, char *argv[])
{
int c;
- srandom(BT_RANDOM_SEED);
+ initstate(BT_RANDOM_SEED, (char *) bt_random_state, sizeof(bt_random_state));
bt_verbose = 0;
bt_filename = argv[0];
bt_test_id = NULL;
is_terminal = isatty(fileno(stdout));
- while ((c = getopt(argc, argv, "lcftv")) >= 0)
+ while ((c = getopt(argc, argv, "lcdftv")) >= 0)
switch (c)
{
case 'l':
do_core = 1;
break;
+ case 'd':
+ do_die = 1;
+ break;
+
case 'f':
no_fork = 1;
break;
bt_syscall(rv < 0, "setrlimit RLIMIT_CORE");
}
+ clock_gettime(CLOCK_MONOTONIC, &bt_begin);
+ bt_suite_case_begin = bt_suite_begin = bt_begin;
+
return;
usage:
- printf("Usage: %s [-l] [-c] [-f] [-t] [-vvv] [<test_suit_name>]\n", argv[0]);
+ printf("Usage: %s [-l] [-c] [-d] [-f] [-t] [-vvv] [<test_suit_name>]\n", argv[0]);
printf("Options: \n");
printf(" -l List all test suite names and descriptions \n");
printf(" -c Force unlimit core dumps (needs root privileges) \n");
+ printf(" -d Die on first failed test case \n");
printf(" -f No forking \n");
printf(" -t No timeout limit \n");
printf(" -v More verbosity, maximum is 3 -vvv \n");
int result;
alarm(timeout);
- if (fn_arg)
- result = fn(fn_arg);
- else
- result = ((int (*)(void))fn)();
+ result = fn(fn_arg);
if (!bt_suite_result)
result = 0;
* levels.
*/
static void
-bt_log_result(int result, const char *fmt, va_list argptr)
+bt_log_result(int result, u64 time, const char *fmt, va_list argptr)
{
static char msg_buf[BT_BUFFER_SIZE];
char *pos;
- snprintf(msg_buf, sizeof(msg_buf), "%s%s%s%s",
+ snprintf(msg_buf, sizeof(msg_buf), "%s%s%s %" PRIu64 ".%09" PRIu64 "s%s",
bt_filename,
bt_test_id ? ": " : "",
bt_test_id ? bt_test_id : "",
+ time / 1000000000,
+ time % 1000000000,
(fmt && strlen(fmt) > 0) ? ": " : "");
pos = msg_buf + strlen(msg_buf);
- vsnprintf(pos, sizeof(msg_buf) - (pos - msg_buf), fmt, argptr);
+ if (fmt)
+ vsnprintf(pos, sizeof(msg_buf) - (pos - msg_buf), fmt, argptr);
int chrs = 0;
for (uint i = 0; i < strlen(msg_buf); i += get_num_terminal_cols())
result_str = is_terminal ? BT_PROMPT_FAIL : BT_PROMPT_FAIL_NO_COLOR;
printf("%s\n", result_str);
+
+ if (do_die && !result)
+ exit(1);
+}
+
+static u64
+get_time_diff(struct timespec *begin)
+{
+ struct timespec end;
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ return (end.tv_sec - begin->tv_sec) * 1000000000ULL
+ + end.tv_nsec - begin->tv_nsec;
}
/**
{
va_list argptr;
va_start(argptr, fmt);
- bt_log_result(result, fmt, argptr);
+ bt_log_result(result, get_time_diff(&bt_begin), fmt, argptr);
va_end(argptr);
}
void
bt_log_suite_result(int result, const char *fmt, ...)
{
- if(bt_verbose >= BT_VERBOSE_SUITE || !result)
+ if (bt_verbose >= BT_VERBOSE_SUITE || !result)
{
va_list argptr;
va_start(argptr, fmt);
- bt_log_result(result, fmt, argptr);
+ bt_log_result(result, get_time_diff(&bt_suite_begin), fmt, argptr);
va_end(argptr);
}
}
{
va_list argptr;
va_start(argptr, fmt);
- bt_log_result(result, fmt, argptr);
+ bt_log_result(result, get_time_diff(&bt_suite_case_begin), fmt, argptr);
va_end(argptr);
}
}
if (bt_verbose >= BT_VERBOSE_ABSOLUTELY_ALL)
bt_log("Starting");
+ clock_gettime(CLOCK_MONOTONIC, &bt_suite_begin);
+ bt_suite_case_begin = bt_suite_begin;
+
if (!forked)
{
bt_suite_result = bt_run_test_fn(fn, fn_arg, timeout);
int i;
for (i = 0; i < opts->ndata; i++)
{
+ if (bt_verbose >= BT_VERBOSE_SUITE)
+ clock_gettime(CLOCK_MONOTONIC, &bt_suite_case_begin);
+
int bt_suit_case_result = opts->test_fn(opts->out_buf, opts->data[i].in, opts->data[i].out);
if (bt_suit_case_result == 0)
bt_fmt_ipa(char *buf, size_t size, const void *data)
{
const ip_addr *ip = data;
- bsnprintf(buf, size, "%I", *ip);
+ if (data)
+ bsnprintf(buf, size, "%I", *ip);
+ else
+ bsnprintf(buf, size, "(null)");
}
int
* Mock-ups of all necessary public functions in main.c
*/
+int parse_and_exit;
char *bird_name;
void async_config(void) {}
void async_dump(void) {}
void async_shutdown(void) {}
+char *get_hostname(linpool *lp UNUSED) { return NULL; }
void cmd_check_config(char *name UNUSED) {}
void cmd_reconfig(char *name UNUSED, int type UNUSED, int timeout UNUSED) {}
void cmd_reconfig_confirm(void) {}
void cmd_reconfig_undo(void) {}
+void cmd_reconfig_status(void) {}
+void cmd_graceful_restart(void) {}
void cmd_shutdown(void) {}
void cmd_reconfig_undo_notify(void) {}