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