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.
16 #include <sys/param.h>
21 #include "../xmalloc.h"
23 static int expected_tests
= NO_PLAN
, failed_tests
, current_test
;
24 static char *todo_mesg
;
26 static char *vstrdupf(const char *fmt
, va_list args
)
36 size
= vsnprintf(NULL
, 0, fmt
, args2
) + 2;
39 vsprintf(str
, fmt
, args
);
45 void cplan(int tests
, const char *fmt
, ...)
47 expected_tests
= tests
;
49 if (tests
== SKIP_ALL
) {
54 why
= vstrdupf(fmt
, args
);
58 note("SKIP %s\n", why
);
64 printf("1..%d\n", tests
);
67 int vok_at_loc(const char *file
, int line
, int test
, const char *fmt
,
70 char *name
= vstrdupf(fmt
, args
);
72 printf("%sok %d", test
? "" : "not ", ++current_test
);
75 printf(" - %s", name
);
79 printf(" %s", todo_mesg
);
86 diag(" Failed%s test '%s'\n at %s line %d.",
87 todo_mesg
? " (TODO)" : "", name
, file
, line
);
89 diag(" Failed%s test at %s line %d.",
90 todo_mesg
? " (TODO)" : "", file
, line
);
99 int ok_at_loc(const char *file
, int line
, int test
, const char *fmt
, ...)
104 vok_at_loc(file
, line
, test
, fmt
, args
);
110 static inline int mystrcmp (const char *a
, const char *b
)
112 return a
== b
? 0 : !a
? -1 : !b
? 1 : strcmp(a
, b
);
115 #define eq(a, b) (!mystrcmp(a, b))
116 #define ne(a, b) (mystrcmp(a, b))
118 int is_at_loc(const char *file
, int line
, const char *got
, const char *expected
,
119 const char *fmt
, ...)
121 int test
= eq(got
, expected
);
125 vok_at_loc(file
, line
, test
, fmt
, args
);
129 diag(" got: '%s'", got
);
130 diag(" expected: '%s'", expected
);
136 int isnt_at_loc(const char *file
, int line
, const char *got
,
137 const char *expected
, const char *fmt
, ...)
139 int test
= ne(got
, expected
);
143 vok_at_loc(file
, line
, test
, fmt
, args
);
147 diag(" got: '%s'", got
);
148 diag(" expected: anything else");
154 int cmp_ok_at_loc(const char *file
, int line
, int a
, const char *op
, int b
,
155 const char *fmt
, ...)
158 int test
= eq(op
, "||") ? a
|| b
159 : eq(op
, "&&") ? a
&& b
160 : 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 : diag("unrecognized operator '%s'", op
);
179 vok_at_loc(file
, line
, test
, fmt
, args
);
191 static void vdiag_to_fh(FILE *fh
, const char *fmt
, va_list args
)
199 mesg
= vstrdupf(fmt
, args
);
202 for (i
= 0; *line
; i
++) {
204 if (!c
|| c
== '\n') {
206 fprintf(fh
, "# %s\n", line
);
218 int diag(const char *fmt
, ...)
223 vdiag_to_fh(stderr
, fmt
, args
);
229 int note(const char *fmt
, ...)
234 vdiag_to_fh(stdout
, fmt
, args
);
240 int exit_status(void)
244 if (expected_tests
== NO_PLAN
) {
245 printf("1..%d\n", current_test
);
246 } else if (current_test
!= expected_tests
) {
247 diag("Looks like you planned %d test%s but ran %d.",
248 expected_tests
, expected_tests
> 1 ? "s" : "",
255 diag("Looks like you failed %d test%s of %d run.",
256 failed_tests
, failed_tests
> 1 ? "s" : "",
259 if (expected_tests
== NO_PLAN
)
260 retval
= failed_tests
;
262 retval
= expected_tests
- current_test
+ failed_tests
;
268 int bail_out(int ignore
, const char *fmt
, ...)
273 printf("Bail out! ");
282 void skippy(int n
, const char *fmt
, ...)
288 why
= vstrdupf(fmt
, args
);
292 printf("ok %d ", ++current_test
);
293 note("skip %s\n", why
);
299 void ctodo(int ignore
, const char *fmt
, ...)
304 todo_mesg
= vstrdupf(fmt
, args
);
314 /* Create a shared memory int to keep track of whether a piece of code
315 * executed dies. to be used in the dies_ok and lives_ok macros */
316 int tap_test_died(int status
)
319 static int *test_died
= NULL
;
322 test_died
= mmap(0, sizeof (int), PROT_READ
| PROT_WRITE
,
323 MAP_SHARED
| MAP_ANONYMOUS
, -1, 0);
333 int like_at_loc(int for_match
, const char *file
, int line
, const char *got
,
334 const char *expected
, const char *fmt
, ...)
340 err
= regcomp(&re
, expected
, REG_EXTENDED
);
343 regerror(err
, &re
, errbuf
, sizeof errbuf
);
344 fprintf(stderr
, "Unable to compile regex '%s': %s "
345 "at %s line %d\n", expected
, errbuf
, file
, line
);
349 err
= regexec(&re
, got
, 0, NULL
, 0);
352 test
= for_match
? !err
: err
;
355 vok_at_loc(file
, line
, test
, fmt
, args
);
361 diag(" doesn't match: '%s'", expected
);
364 diag(" matches: '%s'", expected
);