birdtest.h 5.27 KB
Newer Older
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
/*
 *	BIRD -- Unit Test Framework (BIRD Test)
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#ifndef _BIRDTEST_H_
#define _BIRDTEST_H_

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>

#include "nest/bird.h"


extern int bt_result;
extern int bt_suite_result;
extern char bt_out_fmt_buf[1024];

extern uint bt_verbose;
#define BT_VERBOSE_NO			0
#define BT_VERBOSE_SUITE		1
#define BT_VERBOSE_SUITE_CASE		2
#define BT_VERBOSE_ABSOLUTELY_ALL	3

extern const char *bt_filename;
extern const char *bt_test_id;

void bt_init(int argc, char *argv[]);
int  bt_exit_value(void);
int bt_test_suite_base(int (*test_fn)(const void *), const char *test_id, const void *test_fn_argument, int forked, int timeout, const char *dsc, ...);
long int bt_random(void);

void bt_log_suite_result(int result, const char *fmt, ...);
void bt_log_suite_case_result(int result, const char *fmt, ...);

#define BT_TIMEOUT 			5	/* Default timeout in seconds */
#define BT_FORKING 			1	/* Forking is enabled in default */

#define BT_RANDOM_SEED 			982451653

#define BT_BUFFER_SIZE 			10000

#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_OK_NO_COLOR		" ["                 " OK "                  "] "
#define BT_PROMPT_FAIL			" [" BT_PROMPT_RED   "FAIL" BT_PROMPT_NORMAL "] "
#define BT_PROMPT_FAIL_NO_COLOR		" ["                 "FAIL"                  "] "
#define BT_PROMPT_OK_FAIL_STRLEN	8	/* strlen ' [FAIL] ' */

#define bt_test_suite(fn, dsc, ...) \
  bt_test_suite_extra(fn, BT_FORKING, BT_TIMEOUT, dsc, ##__VA_ARGS__)

#define bt_test_suite_extra(fn, f, t, dsc, ...) \
  bt_test_suite_base((int (*)(const void *))fn, #fn, NULL, f, t, dsc, ##__VA_ARGS__)

#define bt_test_suite_arg(fn, arg, dsc, ...) \
  bt_test_suite_arg_extra(fn, arg, BT_FORKING, BT_TIMEOUT, dsc, ##__VA_ARGS__)

#define bt_test_suite_arg_extra(fn, arg, f, t, dsc, ...) \
  bt_test_suite_base(fn, #fn, arg, f, t, dsc, ##__VA_ARGS__)

#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_log(format, ...) 						\
  do 									\
  {	 								\
    if (bt_test_id) 							\
      printf("%s: %s: " format "\n", bt_filename, bt_test_id, ##__VA_ARGS__); \
    else 								\
      printf("%s: " format "\n", bt_filename, ##__VA_ARGS__);		\
  } while(0)

#define bt_debug(format, ...) 						\
  do 									\
  { 									\
    if (bt_verbose >= BT_VERBOSE_ABSOLUTELY_ALL)			\
      printf(format, ##__VA_ARGS__); 					\
  } while (0)

#define bt_assert(test) \
  bt_assert_msg(test, "Assertion (%s) at %s:%d", #test, __FILE__, __LINE__)

#define bt_assert_msg(test, format, ...)				\
  do									\
  {									\
101
    int bt_suit_case_result = 1;				\
Ondřej Zajíček's avatar
Ondřej Zajíček committed
102 103
    if ((test) == 0) 							\
    {									\
104 105 106
      bt_result = 0;						\
      bt_suite_result = 0;					\
      bt_suit_case_result = 0;					\
Ondřej Zajíček's avatar
Ondřej Zajíček committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    }									\
    bt_log_suite_case_result(bt_suit_case_result, format, ##__VA_ARGS__); \
  } while (0)

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

#define bt_sprintf_concat(s, format, ...) \
    snprintf(s + strlen(s), sizeof(s) - strlen(s), format, ##__VA_ARGS__)

struct bt_pair {
  const void *in;
  const void *out;
};

/* Data structure used by bt_assert_batch() function */
struct bt_batch {
  /* in_fmt / out_fmt - formating data
   * @buf: buffer for write stringified @data
   * @size: empty size in @buf
   * @data: data for stringify
   *
   * There are some build-in functions, see bt_fmt_* functions */
  void (*in_fmt)(char *buf, size_t size, const void *data);
  void (*out_fmt)(char *buf, size_t size, const void *data);

  /* Temporary output buffer */
  void *out_buf;

  /* test_fn - testing function
   * @out: output data from tested function
   * @in: data for input
   * @expected_out: expected data from tested function
   *
   * Input arguments should not be stringified using in_fmt() or out_fmt()
149
   * function already. This function should return only 0 or 1 */
Ondřej Zajíček's avatar
Ondřej Zajíček committed
150 151 152 153 154
  int (*test_fn)(void *out, const void *in, const void *expected_out);

  /* Name of testing function @test_fn */
  const char *test_fn_name;

155
  /* Number of items in data */
Ondřej Zajíček's avatar
Ondřej Zajíček committed
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
  int ndata;

  /* Array of input and expected output pairs */
  struct bt_pair *data;
};

void bt_fmt_str(char *buf, size_t size, const void *data);
void bt_fmt_unsigned(char *buf, size_t size, const void *data);
void bt_fmt_ipa(char *buf, size_t size, const void *data);
int bt_assert_batch__(struct bt_batch *opts);
int bt_is_char(byte c);

#define bt_assert_batch(data__, fn__, in_fmt__, out_fmt__)		\
  bt_assert_batch__(& (struct bt_batch) {				\
    .data = data__,							\
    .ndata = ARRAY_SIZE(data__),					\
    .test_fn = fn__,							\
    .test_fn_name = #fn__,						\
    .in_fmt = in_fmt__,							\
    .out_fmt = out_fmt__,						\
    .out_buf = bt_out_fmt_buf,	/* Global memory for this usage */	\
  })

#endif /* _BIRDTEST_H_ */