]> begriffs open source - libtap/blob - tap.c
Add opening curly brace.
[libtap] / tap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include "tap.h"
6 \r
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
11
12 void plan (int tests) {\r
13     expected_tests = tests;
14     if (tests != NO_PLAN)\r
15         printf("1..%d\n", tests);\r
16 }
17
18 static char *vstrdupf (const char *fmt, va_list args) {
19     char *str;
20     int size = vsnprintf(NULL, 0, fmt, args) + 1;
21     str = malloc(size);
22     vsprintf(str, fmt, args);
23     return str;
24 }
25
26 static int vok_at_loc (const char *file,
27                        int         line,
28                        int         test,
29                        const char *fmt,
30                        va_list     args)
31 {
32     char *name = vstrdupf(fmt, args);
33     printf("%sok %d", test ? "" : "not ", ++current_test);
34     if (*name)
35         printf(" - %s", name);
36     if (todo_mesg) {
37         printf(" # TODO");
38         if (*todo_mesg)
39             printf(" %s", todo_mesg);
40     }
41     printf("\n");\r
42     if (!test) {
43         if (*name)\r
44             diag("  Failed%s test '%s'\n  at %s line %d.",
45                 todo_mesg ? " (TODO)" : "", name, file, line);\r
46         else\r
47             diag("  Failed%s test at %s line %d.",
48                 todo_mesg ? " (TODO)" : "", file, line);
49         if (!todo_mesg)\r
50             failed_tests++;\r
51     }\r
52     free(name);
53     return test;
54 }
55 \r
56 int ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
57     va_list args;
58     va_start(args, fmt);
59     vok_at_loc(file, line, test, fmt, args);
60     va_end(args);
61     return test;\r
62 }\r
63
64 static int mystrcmp (const char *a, const char *b) {
65     return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b);
66 }
67
68 int is_at_loc (const char *file,
69                int         line,
70                const char *got,
71                const char *expected,
72                const char *fmt,
73                ...)
74 {
75     int test = !mystrcmp(got, expected);
76     va_list args;
77     va_start(args, fmt);
78     vok_at_loc(file, line, test, fmt, args);
79     va_end(args);
80     if (!test) {
81         diag("         got: '%s'", got);
82         diag("    expected: '%s'", expected);
83     }
84     return test;
85 }
86
87 int isnt_at_loc (const char *file,
88                  int         line,
89                  const char *got,
90                  const char *expected,
91                  const char *fmt,
92                  ...)
93 {
94     int test = mystrcmp(got, expected);
95     va_list args;
96     va_start(args, fmt);
97     vok_at_loc(file, line, test, fmt, args);
98     va_end(args);
99     if (!test) {
100         diag("         got: '%s'", got);
101         diag("    expected: anything else");
102     }
103     return test;
104 }
105
106 static void vdiag_to_fh (FILE *fh, const char *fmt, va_list args) {\r
107     char *mesg, *line;
108     int i;\r
109     if (!fmt)
110         return;\r
111     mesg = vstrdupf(fmt, args);\r
112     line = mesg;\r
113     for (i = 0; *line; i++) {\r
114         char c = mesg[i];\r
115         if (!c || c == '\n') {\r
116             mesg[i] = '\0';\r
117             fprintf(fh, "# %s\n", line);\r
118             if (!c) break;\r
119             mesg[i] = c;\r
120             line = &mesg[i+1];\r
121         }\r
122     }\r
123     free(mesg);
124     return;\r
125 }\r
126
127 int diag (const char *fmt, ...) {
128     va_list args;
129     va_start(args, fmt);
130     vdiag_to_fh(stderr, fmt, args);
131     va_end(args);
132     return 1;
133 }
134
135 int note (const char *fmt, ...) {
136     va_list args;
137     va_start(args, fmt);
138     vdiag_to_fh(stdout, fmt, args);
139     va_end(args);
140     return 1;
141 }
142 \r
143 int exit_status () {\r
144     int retval = 0;\r
145     if (expected_tests == NO_PLAN) {\r
146         printf("1..%d\n", current_test);\r
147     }\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
151         retval = 255;\r
152     }\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;
158         else
159             retval = expected_tests - current_test + failed_tests;\r
160     }\r
161     return retval;\r
162 }
163
164 void skippy (int n, const char *fmt, ...) {
165     char *why;
166     va_list args;
167     va_start(args, fmt);
168     why = vstrdupf(fmt, args);
169     va_end(args);
170     while (n --> 0) {
171         printf("ok %d ", ++current_test);
172         note("skip %s\n", why);
173     }
174     free(why);
175 }
176
177 void ctodo (int ignore, const char *fmt, ...) {
178     va_list args;
179     va_start(args, fmt);
180     todo_mesg = vstrdupf(fmt, args);
181     va_end(args);
182 }
183
184 void cendtodo () {
185     free(todo_mesg);
186     todo_mesg = NULL;
187 }
188
189 #ifndef _WIN32
190 #   include <sys/mman.h>
191 #   include <regex.h>
192
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;
197         int prev;
198         if (!test_died) {
199             test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE,
200                              MAP_SHARED | MAP_ANONYMOUS, -1, 0);
201             *test_died = 0;
202         }
203         prev = *test_died;
204         *test_died = status;
205         return prev;
206     }
207
208     int like_at_loc (int         for_match,
209                      const char *file,
210                      int         line,
211                      const char *got,
212                      const char *expected,
213                      const char *fmt,
214                      ...)
215     {
216         int test;
217         regex_t re;
218         int err = regcomp(&re, expected, REG_EXTENDED);
219         if (err) {
220             char errbuf[256];
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);
224             exit(255);
225         }
226         err = regexec(&re, got, 0, NULL, 0);
227         regfree(&re);
228         test = for_match ? !err : err;
229         va_list args;
230         va_start(args, fmt);
231         vok_at_loc(file, line, test, fmt, args);
232         va_end(args);
233         if (!test) {
234             if (for_match) {
235                 diag("                   '%s'", got);
236                 diag("    doesn't match: '%s'", expected);
237             }
238             else {
239                 diag("                   '%s'", got);
240                 diag("          matches: '%s'", expected);
241             }
242         }
243         return test;
244     }
245 #endif
246