2 libtap - Write tests in C
3 Copyright 2012 Jake Gelbman <gelbman@gmail.com>
4 This file is licensed under the GPLv2
13 static int expected_tests = NO_PLAN;
14 static int failed_tests;
15 static int current_test;
16 static char *todo_mesg;
19 vstrdupf (const char *fmt, va_list args) {
26 size = vsnprintf(NULL, 0, fmt, args2) + 2;
29 perror("malloc error");
32 vsprintf(str, fmt, args);
38 planf (int tests, const char *fmt, ...) {
39 expected_tests = tests;
40 if (tests == SKIP_ALL) {
44 why = vstrdupf(fmt, args);
47 note("SKIP %s\n", why);
50 if (tests != NO_PLAN) {
51 printf("1..%d\n", tests);
56 vok_at_loc (const char *file, int line, int test, const char *fmt,
59 char *name = vstrdupf(fmt, args);
60 printf("%sok %d", test ? "" : "not ", ++current_test);
62 printf(" - %s", name);
66 printf(" %s", todo_mesg);
71 diag(" Failed%s test '%s'\n at %s line %d.",
72 todo_mesg ? " (TODO)" : "", name, file, line);
74 diag(" Failed%s test at %s line %d.",
75 todo_mesg ? " (TODO)" : "", file, line);
84 ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
87 vok_at_loc(file, line, test, fmt, args);
93 mystrcmp (const char *a, const char *b) {
94 return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b);
97 #define eq(a, b) (!mystrcmp(a, b))
98 #define ne(a, b) (mystrcmp(a, b))
101 is_at_loc (const char *file, int line, const char *got, const char *expected,
102 const char *fmt, ...)
104 int test = eq(got, expected);
107 vok_at_loc(file, line, test, fmt, args);
110 diag(" got: '%s'", got);
111 diag(" expected: '%s'", expected);
117 isnt_at_loc (const char *file, int line, const char *got, const char *expected,
118 const char *fmt, ...)
120 int test = ne(got, expected);
123 vok_at_loc(file, line, test, fmt, args);
126 diag(" got: '%s'", got);
127 diag(" expected: anything else");
133 cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b,
134 const char *fmt, ...)
136 int test = eq(op, "||") ? a || b
137 : eq(op, "&&") ? a && b
138 : eq(op, "|") ? a | b
139 : eq(op, "^") ? a ^ b
140 : eq(op, "&") ? a & b
141 : eq(op, "==") ? a == b
142 : eq(op, "!=") ? a != b
143 : eq(op, "<") ? a < b
144 : eq(op, ">") ? a > b
145 : eq(op, "<=") ? a <= b
146 : eq(op, ">=") ? a >= b
147 : eq(op, "<<") ? a << b
148 : eq(op, ">>") ? a >> b
149 : eq(op, "+") ? a + b
150 : eq(op, "-") ? a - b
151 : eq(op, "*") ? a * b
152 : eq(op, "/") ? a / b
153 : eq(op, "%") ? a % b
154 : diag("unrecognized operator '%s'", op);
157 vok_at_loc(file, line, test, fmt, args);
168 vdiag_to_fh (FILE *fh, const char *fmt, va_list args) {
173 mesg = vstrdupf(fmt, args);
175 for (i = 0; *line; i++) {
177 if (!c || c == '\n') {
179 fprintf(fh, "# %s\n", line);
191 diag (const char *fmt, ...) {
194 vdiag_to_fh(stderr, fmt, args);
200 note (const char *fmt, ...) {
203 vdiag_to_fh(stdout, fmt, args);
211 if (expected_tests == NO_PLAN) {
212 printf("1..%d\n", current_test);
214 else if (current_test != expected_tests) {
215 diag("Looks like you planned %d test%s but ran %d.",
216 expected_tests, expected_tests > 1 ? "s" : "", current_test);
220 diag("Looks like you failed %d test%s of %d run.",
221 failed_tests, failed_tests > 1 ? "s" : "", current_test);
222 if (expected_tests == NO_PLAN)
223 retval = failed_tests;
225 retval = expected_tests - current_test + failed_tests;
231 bail_out (int ignore, const char *fmt, ...) {
234 printf("Bail out! ");
243 skippy (int n, const char *fmt, ...) {
247 why = vstrdupf(fmt, args);
250 printf("ok %d ", ++current_test);
251 note("skip %s\n", why);
257 todof (int ignore, const char *fmt, ...) {
260 todo_mesg = vstrdupf(fmt, args);
271 #include <sys/mman.h>
272 #include <sys/param.h>
275 #if defined __APPLE__ || defined BSD
276 #define MAP_ANONYMOUS MAP_ANON
279 /* Create a shared memory int to keep track of whether a piece of code executed
280 dies. to be used in the dies_ok and lives_ok macros. */
282 tap_test_died (int status) {
283 static int *test_died = NULL;
286 test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE,
287 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
296 like_at_loc (int for_match, const char *file, int line, const char *got,
297 const char *expected, const char *fmt, ...)
302 int err = regcomp(&re, expected, REG_EXTENDED);
305 regerror(err, &re, errbuf, sizeof errbuf);
306 fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n",
307 expected, errbuf, file, line);
310 err = regexec(&re, got, 0, NULL, 0);
312 test = for_match ? !err : err;
314 vok_at_loc(file, line, test, fmt, args);
319 diag(" doesn't match: '%s'", expected);
323 diag(" matches: '%s'", expected);