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