7 static int expected_tests = NO_PLAN;
\r
8 static int failed_tests;
\r
9 static int current_test;
10 static char *todo_mesg;
\r
12 void plan (int tests) {
\r
13 expected_tests = tests;
14 if (tests != NO_PLAN)
\r
15 printf("1..%d\n", tests);
\r
18 static char *vstrdupf (const char *fmt, va_list args) {
20 int size = vsnprintf(NULL, 0, fmt, args) + 1;
22 vsprintf(str, fmt, args);
26 static int vok_at_loc (const char *file,
32 char *name = vstrdupf(fmt, args);
33 printf("%sok %d", test ? "" : "not ", ++current_test);
35 printf(" - %s", name);
39 printf(" %s", todo_mesg);
44 diag(" Failed%s test '%s'\n at %s line %d.",
45 todo_mesg ? " (TODO)" : "", name, file, line);
\r
47 diag(" Failed%s test at %s line %d.",
48 todo_mesg ? " (TODO)" : "", file, line);
56 int ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
59 vok_at_loc(file, line, test, fmt, args);
64 static int mystrcmp (const char *a, const char *b) {
65 return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b);
68 int is_at_loc (const char *file,
75 int test = !mystrcmp(got, expected);
78 vok_at_loc(file, line, test, fmt, args);
81 diag(" got: '%s'", got);
82 diag(" expected: '%s'", expected);
87 int isnt_at_loc (const char *file,
94 int test = mystrcmp(got, expected);
97 vok_at_loc(file, line, test, fmt, args);
100 diag(" got: '%s'", got);
101 diag(" expected: anything else");
106 static void vdiag_to_fh (FILE *fh, const char *fmt, va_list args) {
\r
111 mesg = vstrdupf(fmt, args);
\r
113 for (i = 0; *line; i++) {
\r
115 if (!c || c == '\n') {
\r
117 fprintf(fh, "# %s\n", line);
\r
127 int diag (const char *fmt, ...) {
130 vdiag_to_fh(stderr, fmt, args);
135 int note (const char *fmt, ...) {
138 vdiag_to_fh(stdout, fmt, args);
143 int exit_status () {
\r
145 if (expected_tests == NO_PLAN) {
\r
146 printf("1..%d\n", current_test);
\r
148 else if (current_test != expected_tests) {
\r
149 diag("Looks like you planned %d test%s but ran %d.",
\r
150 expected_tests, expected_tests > 1 ? "s" : "", current_test);
\r
153 if (failed_tests) {
\r
154 diag("Looks like you failed %d test%s of %d run.",
\r
155 failed_tests, failed_tests > 1 ? "s" : "", current_test);
156 if (expected_tests == NO_PLAN)
\r
157 retval = failed_tests;
159 retval = expected_tests - current_test + failed_tests;
\r
164 void skippy (int n, const char *fmt, ...) {
168 why = vstrdupf(fmt, args);
171 printf("ok %d ", ++current_test);
172 note("skip %s\n", why);
177 void ctodo (int ignore, const char *fmt, ...) {
180 todo_mesg = vstrdupf(fmt, args);
190 # include <sys/mman.h>
193 /* Create a shared memory int to keep track of whether a piece of code
194 executed dies. to be used in the dies_ok and lives_ok macros */
195 int tap_test_died (int status) {
196 static int *test_died = NULL;
199 test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE,
200 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
208 int like_at_loc (int for_match,
212 const char *expected,
218 int err = regcomp(&re, expected, REG_EXTENDED);
221 regerror(err, &re, errbuf, sizeof errbuf);
222 fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n",
223 expected, errbuf, file, line);
226 err = regexec(&re, got, 0, NULL, 0);
228 test = for_match ? !err : err;
231 vok_at_loc(file, line, test, fmt, args);
236 diag(" doesn't match: '%s'", expected);
240 diag(" matches: '%s'", expected);