Commit 1ce8d33b authored by Pavel Tvrdík's avatar Pavel Tvrdík
Browse files

Birdtest: Improve the testing framework

- non-blocking asserts, only set bt_test_suite_success
- unification of testing output from bt_assert_fn_in_out and bt_assert_out_fn_in
parent 84dbe05f
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ const char *bt_filename;
const char *bt_test_id;

int bt_success;
int bt_test_case_success;
int bt_test_suite_success;

int
bt_rand_num(void)
@@ -132,7 +132,7 @@ 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_suite_success = 1;

  bt_test_id = test_id;

@@ -143,6 +143,7 @@ bt_test_suite5(int (*test_fn)(void), const char *test_id, const char *dsc, int f
  {
    alarm(timeout);
    result = test_fn();
    result &= bt_test_suite_success;
  }
  else
  {
@@ -153,6 +154,7 @@ bt_test_suite5(int (*test_fn)(void), const char *test_id, const char *dsc, int f
    {
      alarm(timeout);
      result = test_fn();
      result &= bt_test_suite_success;
      _exit(result);
    }

@@ -199,11 +201,12 @@ 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);
    snprintf(msg_buf, sizeof(char)*BT_BUFFER_SIZE, "%s: ", bt_filename);

    va_list argptr;
    va_start(argptr, to_left_align_msg);
    vsnprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf), to_left_align_msg, argptr);

    char fmt_buf[BT_BUFFER_SIZE];
@@ -220,3 +223,14 @@ bt_end(void)
{
  return !bt_success;
}

void
bt_strncat_(char *buf, size_t buf_size, const char *str, ...)
{
  if (str != NULL)
  {
    va_list argptr;
    va_start(argptr, str);
    vsnprintf(buf + strlen(buf), buf_size, str, argptr);
  }
}
+86 −50
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
#include <errno.h>

extern int bt_success;
extern int bt_test_case_success;
extern int bt_test_suite_success;

extern int bt_verbose;
#define BT_VERBOSE_NOTHING		0
@@ -91,78 +91,114 @@ void bt_result(const char *result, const char *msg, ...);
#define bt_assert(test) \
    bt_assert_msg(test, "Assertion (%s) failed at %s:%d", #test, __FILE__, __LINE__)

#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_case_success = 0; \
    } } while (0)
    do 											\
    {											\
      if (!(test))									\
      { 										\
	if (bt_verbose)									\
	  bt_log(format, ##__VA_ARGS__); 						\
	bt_success = bt_test_suite_success = 0; 					\
      }											\
    } while (0)

#define bt_syscall(test,format, ...) \
    do { if (test) { bt_log(format ": %s", ##__VA_ARGS__, strerror(errno)); exit(3); } } while (0)

#define bt_assert_fn_in(fn, in_out, in_fmt, out_fmt)					\

#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)							\
    do											\
    {											\
      unsigned int i;									\
      for (i = 0; i < (sizeof(in_out)/sizeof(in_out[0])); i++)				\
      u32 *pc = (u32*) data;								\
      bt_strncat(buf, "{");								\
      for (i = 0; i < (sizeof(*data) / sizeof(typeof(*pc))); i++)			\
	bt_strncat(buf, "%s0x%08X", (i ? ", " : ""), pc[i]);				\
      bt_strncat(buf, "}");								\
    } while (0)

#define bt_dump(buf, data, fmt)								\
    do											\
    {											\
	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)); \
      if (fmt == NULL)									\
	bt_dump_struct(buf, &data);							\
      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); \
      }											\
	bt_strncat_(buf, sizeof(buf), fmt, data);					\
    } while (0)

#define bt_assert_fn_in_out(fn, in_out, in_fmt, out_fmt)				\
#define bt_print_result_line(fn, in, out, fn_out, in_fmt, out_fmt, result)		\
    do											\
    {											\
      unsigned int i;									\
      for (i = 0; i < (sizeof(in_out)/sizeof(in_out[0])); i++)				\
      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) 									\
      {											\
	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); \
	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)

#define bt_strcat(buf, str, ...) snprintf(buf + strlen(buf), sizeof(buf), str, ##__VA_ARGS__)

#define bt_dump_struct(buf, data)							\
/**
 * 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)				\
    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, "}");								\
      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); \
      }											\
    } while (0)

#define bt_assert_fn_in_out_struct(fn, in_out, in_fmt)					\
/**
 * 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)				\
    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); \
	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); \
      }											\
    } while (0)