Git fork
at reftables-rust 183 lines 5.9 kB view raw
1#ifndef TEST_LIB_H 2#define TEST_LIB_H 3 4#include "git-compat-util.h" 5 6/* 7 * Run a test function, returns 1 if the test succeeds, 0 if it 8 * fails. If test_skip_all() has been called then the test will not be 9 * run. The description for each test should be unique. For example: 10 * 11 * TEST(test_something(arg1, arg2), "something %d %d", arg1, arg2) 12 */ 13#define TEST(t, ...) \ 14 test__run_end(test__run_begin() ? 0 : (t, 1), \ 15 TEST_LOCATION(), __VA_ARGS__) 16 17/* 18 * Run a test unless test_skip_all() has been called. Acts like a 19 * conditional; the test body is expected as a statement or block after 20 * the closing parenthesis. The description for each test should be 21 * unique. E.g.: 22 * 23 * if_test ("something else %d %d", arg1, arg2) { 24 * prepare(); 25 * test_something_else(arg1, arg2); 26 * cleanup(); 27 * } 28 */ 29#define if_test(...) \ 30 if (test__run_begin() ? \ 31 (test__run_end(0, TEST_LOCATION(), __VA_ARGS__), 0) : \ 32 (test__run_describe(TEST_LOCATION(), __VA_ARGS__), 1)) 33 34/* 35 * Print a test plan, should be called before any tests. If the number 36 * of tests is not known in advance test_done() will automatically 37 * print a plan at the end of the test program. 38 */ 39void test_plan(int count); 40 41/* 42 * test_done() must be called at the end of main(). It will print the 43 * plan if plan() was not called at the beginning of the test program 44 * and returns the exit code for the test program. 45 */ 46int test_done(void); 47 48/* Skip the current test. */ 49__attribute__((format (printf, 1, 2))) 50void test_skip(const char *format, ...); 51 52/* Skip all remaining tests. */ 53__attribute__((format (printf, 1, 2))) 54void test_skip_all(const char *format, ...); 55 56/* Print a diagnostic message to stdout. */ 57__attribute__((format (printf, 1, 2))) 58void test_msg(const char *format, ...); 59 60/* 61 * Test checks are built around test_assert(). checks return 1 on 62 * success, 0 on failure. If any check fails then the test will fail. To 63 * create a custom check define a function that wraps test_assert() and 64 * a macro to wrap that function to provide a source location and 65 * stringified arguments. Custom checks that take pointer arguments 66 * should be careful to check that they are non-NULL before 67 * dereferencing them. For example: 68 * 69 * static int check_oid_loc(const char *loc, const char *check, 70 * struct object_id *a, struct object_id *b) 71 * { 72 * int res = test_assert(loc, check, a && b && oideq(a, b)); 73 * 74 * if (!res) { 75 * test_msg(" left: %s", a ? oid_to_hex(a) : "NULL"; 76 * test_msg(" right: %s", b ? oid_to_hex(a) : "NULL"; 77 * 78 * } 79 * return res; 80 * } 81 * 82 * #define check_oid(a, b) \ 83 * check_oid_loc(TEST_LOCATION(), "oideq("#a", "#b")", a, b) 84 */ 85int test_assert(const char *location, const char *check, int ok); 86 87/* Helper macro to pass the location to checks */ 88#define TEST_LOCATION() TEST__MAKE_LOCATION(__LINE__) 89 90/* Check a boolean condition. */ 91#define check(x) \ 92 check_bool_loc(TEST_LOCATION(), #x, x) 93int check_bool_loc(const char *loc, const char *check, int ok); 94 95/* 96 * Compare the equality of two pointers of same type. Prints a message 97 * with the two values if the equality fails. NB this is not thread 98 * safe. 99 */ 100#define check_pointer_eq(a, b) \ 101 (test__tmp[0].p = (a), test__tmp[1].p = (b), \ 102 check_pointer_eq_loc(TEST_LOCATION(), #a" == "#b, \ 103 test__tmp[0].p == test__tmp[1].p, \ 104 test__tmp[0].p, test__tmp[1].p)) 105int check_pointer_eq_loc(const char *loc, const char *check, int ok, 106 const void *a, const void *b); 107 108/* 109 * Compare two integers. Prints a message with the two values if the 110 * comparison fails. NB this is not thread safe. 111 */ 112#define check_int(a, op, b) \ 113 (test__tmp[0].i = (a), test__tmp[1].i = (b), \ 114 check_int_loc(TEST_LOCATION(), #a" "#op" "#b, \ 115 test__tmp[0].i op test__tmp[1].i, \ 116 test__tmp[0].i, test__tmp[1].i)) 117int check_int_loc(const char *loc, const char *check, int ok, 118 intmax_t a, intmax_t b); 119 120/* 121 * Compare two unsigned integers. Prints a message with the two values 122 * if the comparison fails. NB this is not thread safe. 123 */ 124#define check_uint(a, op, b) \ 125 (test__tmp[0].u = (a), test__tmp[1].u = (b), \ 126 check_uint_loc(TEST_LOCATION(), #a" "#op" "#b, \ 127 test__tmp[0].u op test__tmp[1].u, \ 128 test__tmp[0].u, test__tmp[1].u)) 129int check_uint_loc(const char *loc, const char *check, int ok, 130 uintmax_t a, uintmax_t b); 131 132/* 133 * Compare two chars. Prints a message with the two values if the 134 * comparison fails. NB this is not thread safe. 135 */ 136#define check_char(a, op, b) \ 137 (test__tmp[0].c = (a), test__tmp[1].c = (b), \ 138 check_char_loc(TEST_LOCATION(), #a" "#op" "#b, \ 139 test__tmp[0].c op test__tmp[1].c, \ 140 test__tmp[0].c, test__tmp[1].c)) 141int check_char_loc(const char *loc, const char *check, int ok, 142 char a, char b); 143 144/* Check whether two strings are equal. */ 145#define check_str(a, b) \ 146 check_str_loc(TEST_LOCATION(), "!strcmp("#a", "#b")", a, b) 147int check_str_loc(const char *loc, const char *check, 148 const char *a, const char *b); 149 150/* 151 * Wrap a check that is known to fail. If the check succeeds then the 152 * test will fail. Returns 1 if the check fails, 0 if it 153 * succeeds. For example: 154 * 155 * TEST_TODO(check(0)); 156 */ 157#define TEST_TODO(check) \ 158 (test__todo_begin(), test__todo_end(TEST_LOCATION(), #check, check)) 159 160/* Private helpers */ 161 162#define TEST__STR(x) #x 163#define TEST__MAKE_LOCATION(line) __FILE__ ":" TEST__STR(line) 164 165union test__tmp { 166 intmax_t i; 167 uintmax_t u; 168 char c; 169 const void *p; 170}; 171 172extern union test__tmp test__tmp[2]; 173 174__attribute__((format (printf, 2, 3))) 175void test__run_describe(const char *, const char *, ...); 176 177int test__run_begin(void); 178__attribute__((format (printf, 3, 4))) 179int test__run_end(int, const char *, const char *, ...); 180void test__todo_begin(void); 181int test__todo_end(const char *, const char *, int); 182 183#endif /* TEST_LIB_H */