2 * transsip - the telephony toolkit
3 * libtap (Write tests in C, by Jake Gelbman)
4 * Copyright 2012 Jake Gelbman <gelbman@gmail.com>
5 * Copyright 2012 Daniel Borkmann <borkmann@iogearbox.net>
6 * Subject to the GPL, version 2.
14 #include <sys/param.h>
19 #include "../xmalloc.h"
20 #include "../xutils.h"
22 static int expected_tests
= NO_PLAN
, failed_tests
, current_test
;
23 static char *todo_mesg
;
25 static char *vstrdupf(const char *fmt
, va_list args
)
35 size
= vsnprintf(NULL
, 0, fmt
, args2
) + 2;
38 vsprintf(str
, fmt
, args
);
44 void cplan(int tests
, const char *fmt
, ...)
46 expected_tests
= tests
;
48 if (tests
== SKIP_ALL
) {
53 why
= vstrdupf(fmt
, args
);
57 note("SKIP %s\n", why
);
63 printf("1..%d\n", tests
);
66 int vok_at_loc(const char *file
, int line
, int test
, const char *fmt
,
69 char *name
= vstrdupf(fmt
, args
);
71 printf("%sok %d", test
? colorize_start(green
) colorize_start(bold
) :
72 colorize_start(red
) colorize_start(bold
) "not ", ++current_test
);
75 printf(" - %s", name
);
79 printf(" %s", todo_mesg
);
82 printf("%s\n", colorize_end());
86 diag(" %sFailed%s test '%s'\n at %s line %d.%s",
87 colorize_start(red
), todo_mesg
? " (TODO)" : "",
88 name
, file
, line
, colorize_end());
90 diag(" %sFailed%s test at %s line %d.%s",
91 colorize_start(red
), todo_mesg
? " (TODO)" : "",
92 file
, line
, colorize_end());
101 int ok_at_loc(const char *file
, int line
, int test
, const char *fmt
, ...)
106 vok_at_loc(file
, line
, test
, fmt
, args
);
112 static inline int mystrcmp (const char *a
, const char *b
)
114 return a
== b
? 0 : !a
? -1 : !b
? 1 : strcmp(a
, b
);
117 #define eq(a, b) (!mystrcmp(a, b))
118 #define ne(a, b) (mystrcmp(a, b))
120 int is_at_loc(const char *file
, int line
, const char *got
, const char *expected
,
121 const char *fmt
, ...)
123 int test
= eq(got
, expected
);
127 vok_at_loc(file
, line
, test
, fmt
, args
);
131 diag(" %sgot: '%s'", colorize_start(red
), got
);
132 diag(" expected: '%s'%s", expected
, colorize_end());
138 int isnt_at_loc(const char *file
, int line
, const char *got
,
139 const char *expected
, const char *fmt
, ...)
141 int test
= ne(got
, expected
);
145 vok_at_loc(file
, line
, test
, fmt
, args
);
149 diag(" %sgot: '%s'", colorize_start(red
), got
);
150 diag(" expected: anything else%s", colorize_end());
156 int cmp_ok_at_loc(const char *file
, int line
, int a
, const char *op
, int b
,
157 const char *fmt
, ...)
160 int test
= eq(op
, "||") ? a
|| b
161 : eq(op
, "&&") ? a
&& b
162 : eq(op
, "|") ? a
| b
163 : eq(op
, "^") ? a
^ b
164 : eq(op
, "&") ? a
& b
165 : eq(op
, "==") ? a
== b
166 : eq(op
, "!=") ? a
!= b
167 : eq(op
, "<") ? a
< b
168 : eq(op
, ">") ? a
> b
169 : eq(op
, "<=") ? a
<= b
170 : eq(op
, ">=") ? a
>= b
171 : eq(op
, "<<") ? a
<< b
172 : eq(op
, ">>") ? a
>> b
173 : eq(op
, "+") ? a
+ b
174 : eq(op
, "-") ? a
- b
175 : eq(op
, "*") ? a
* b
176 : eq(op
, "/") ? a
/ b
177 : eq(op
, "%") ? a
% b
178 : diag("unrecognized operator '%s'", op
);
181 vok_at_loc(file
, line
, test
, fmt
, args
);
185 diag(" %s%d", colorize_start(red
), a
);
187 diag(" %d%s", b
, colorize_end());
193 static void vdiag_to_fh(FILE *fh
, const char *fmt
, va_list args
)
201 mesg
= vstrdupf(fmt
, args
);
204 for (i
= 0; *line
; i
++) {
206 if (!c
|| c
== '\n') {
208 fprintf(fh
, "%s# %s%s\n", colorize_start(red
),
209 line
, colorize_end());
221 int diag(const char *fmt
, ...)
226 vdiag_to_fh(stderr
, fmt
, args
);
232 int note(const char *fmt
, ...)
237 vdiag_to_fh(stdout
, fmt
, args
);
243 int exit_status(void)
247 if (expected_tests
== NO_PLAN
) {
248 printf("1..%d\n", current_test
);
249 } else if (current_test
!= expected_tests
) {
250 diag("Looks like you planned %d test%s but ran %d.",
251 expected_tests
, expected_tests
> 1 ? "s" : "",
258 diag("Looks like you failed %d test%s of %d run.",
259 failed_tests
, failed_tests
> 1 ? "s" : "",
262 if (expected_tests
== NO_PLAN
)
263 retval
= failed_tests
;
265 retval
= expected_tests
- current_test
+ failed_tests
;
271 int bail_out(int ignore
, const char *fmt
, ...)
276 printf("Bail out! ");
285 void skippy(int n
, const char *fmt
, ...)
291 why
= vstrdupf(fmt
, args
);
295 printf("ok %d ", ++current_test
);
296 note("skip %s\n", why
);
302 void ctodo(int ignore
, const char *fmt
, ...)
307 todo_mesg
= vstrdupf(fmt
, args
);
317 /* Create a shared memory int to keep track of whether a piece of code
318 * executed dies. to be used in the dies_ok and lives_ok macros */
319 int tap_test_died(int status
)
322 static int *test_died
= NULL
;
325 test_died
= mmap(0, sizeof (int), PROT_READ
| PROT_WRITE
,
326 MAP_SHARED
| MAP_ANONYMOUS
, -1, 0);
336 int like_at_loc(int for_match
, const char *file
, int line
, const char *got
,
337 const char *expected
, const char *fmt
, ...)
343 err
= regcomp(&re
, expected
, REG_EXTENDED
);
346 regerror(err
, &re
, errbuf
, sizeof errbuf
);
347 fprintf(stderr
, "Unable to compile regex '%s': %s "
348 "at %s line %d\n", expected
, errbuf
, file
, line
);
352 err
= regexec(&re
, got
, 0, NULL
, 0);
355 test
= for_match
? !err
: err
;
358 vok_at_loc(file
, line
, test
, fmt
, args
);
364 diag(" doesn't match: '%s'", expected
);
367 diag(" matches: '%s'", expected
);