Git fork
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 */