]> begriffs open source - libtap/blob - tap.c
Fix README
[libtap] / tap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include "tap.h"
5 \r
6 static int expected_tests = NO_PLAN;\r
7 static int failed_tests;\r
8 static int current_test;
9 static char *todo_mesg = NULL;\r
10
11 void plan (int tests) {\r
12     expected_tests = tests;\r
13     if (tests != NO_PLAN)\r
14         printf("1..%d\n", tests);\r
15 }
16
17 static char *vstrdupf (const char *fmt, va_list args) {
18     char *str;
19     int size = vsnprintf(NULL, 0, fmt, args) + 1;
20     str = malloc(size);
21     vsprintf(str, fmt, args);
22     return str;
23 }
24 \r
25 int ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
26     va_list args;
27     char *name = "";
28     if (fmt) {\r
29         va_start(args, fmt);
30         name = vstrdupf(fmt, args);\r
31         va_end(args);
32     }
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     if (fmt)
53         free(name);
54     return test;\r
55 }\r
56 \r
57 static void vdiag_to_fh (FILE *fh, const char *fmt, va_list args) {\r
58     char *mesg, *line;
59     int i;\r
60     if (!fmt)
61         return;\r
62     mesg = vstrdupf(fmt, args);\r
63     line = mesg;\r
64     for (i = 0; *line; i++) {\r
65         char c = mesg[i];\r
66         if (!c || c == '\n') {\r
67             mesg[i] = '\0';\r
68             fprintf(fh, "# %s\n", line);\r
69             if (!c) break;\r
70             mesg[i] = c;\r
71             line = &mesg[i+1];\r
72         }\r
73     }\r
74     free(mesg);
75     return;\r
76 }\r
77
78 int diag (const char *fmt, ...) {
79     va_list args;
80     va_start(args, fmt);
81     vdiag_to_fh(stderr, fmt, args);
82     va_end(args);
83     return 1;
84 }
85
86 int note (const char *fmt, ...) {
87     va_list args;
88     va_start(args, fmt);
89     vdiag_to_fh(stdout, fmt, args);
90     va_end(args);
91     return 1;
92 }
93 \r
94 int exit_status () {\r
95     int retval = EXIT_SUCCESS;\r
96     if (expected_tests == NO_PLAN) {\r
97         printf("1..%d\n", current_test);\r
98     }\r
99     else if (current_test != expected_tests) {\r
100         diag("Looks like you planned %d test%s but ran %d.",\r
101             expected_tests, expected_tests > 1 ? "s" : "", current_test);\r
102         retval = EXIT_FAILURE;\r
103     }\r
104     if (failed_tests) {\r
105         diag("Looks like you failed %d test%s of %d run.",\r
106             failed_tests, failed_tests > 1 ? "s" : "", current_test);\r
107         retval = EXIT_FAILURE;\r
108     }\r
109     return retval;\r
110 }
111
112 void skippy (int n, const char *fmt, ...) {
113     char *why;
114     va_list args;
115     va_start(args, fmt);
116     why = vstrdupf(fmt, args);
117     va_end(args);
118     while (n --> 0) {
119         printf("ok %d ", ++current_test);
120         note("skip %s\n", why);
121     }
122     free(why);
123 }
124
125 void ctodo (int ignore, const char *fmt, ...) {
126     va_list args;
127     va_start(args, fmt);
128     todo_mesg = vstrdupf(fmt, args);
129     va_end(args);
130 }
131
132 void cendtodo () {
133     free(todo_mesg);
134     todo_mesg = NULL;
135 }
136
137 #ifndef _WIN32
138 #   include <sys/mman.h>
139     /* Create a shared memory int to keep track of whether a piece of code 
140     executed dies. to be used in the dies_ok and lives_ok macros  */
141     int tap_test_died (int status) {
142         static int *test_died = NULL;
143         int prev;
144         if (!test_died) {
145             test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE,
146                              MAP_SHARED | MAP_ANONYMOUS, -1, 0);
147             *test_died = 0;
148         }
149         prev = *test_died;
150         *test_died = status;
151         return prev;
152     }
153 #endif
154