]> begriffs open source - libtap/blob - tap.c
first commit
[libtap] / tap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <sys/mman.h>\r
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;\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 \r
17 int ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
18     va_list args;
19     char *name = "";
20     
21     if (fmt) {\r
22         va_start(args, fmt);
23         vasprintf(&name, fmt, args);\r
24         va_end(args);
25     }\r
26     \r
27     printf("%sok %d%s%s\n",
28         test ? "" : "not ",
29         ++current_test,
30         *name ? " - " : "",
31         name);\r
32     \r
33     if (!test) {
34         if (*name)\r
35             diag("  Failed test '%s'\n  at %s line %d.", name, file, line);\r
36         else\r
37             diag("  Failed test at %s line %d.", file, line);\r
38         failed_tests++;\r
39     }\r
40     
41     if (fmt) free(name);
42 \r
43     return test;\r
44 }\r
45 \r
46 static void diag_to_fh_v (FILE *fh, const char *fmt, va_list args) {\r
47     char *mesg, *line;
48     int i;\r
49
50     if (!fmt) return;\r
51     vasprintf(&mesg, fmt, args);\r
52     \r
53     line = mesg;\r
54     for (i = 0; *line; i++) {\r
55         char c = mesg[i];\r
56         if (!c || c == '\n') {\r
57             mesg[i] = '\0';\r
58             fprintf(fh, "# %s\n", line);\r
59             if (!c) break;\r
60             mesg[i] = c;\r
61             line = &mesg[i+1];\r
62         }\r
63     }\r
64     
65     free(mesg);
66     \r
67     return;\r
68 }\r
69
70 int diag (const char *fmt, ...) {
71     va_list args;
72     va_start(args, fmt);
73     diag_to_fh_v(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     diag_to_fh_v(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 /* Create a shared memory int to keep track of whether a piece of code 
105 executed dies. to be used in the dies_ok and lives_ok macros  */
106 int tap_test_died (int b) {
107     static int *test_died = NULL;
108     
109     if (!test_died) {
110         test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE,
111                          MAP_SHARED | MAP_ANONYMOUS, -1, 0);
112     }
113     
114     int prev = *test_died;
115     *test_died = b;
116     return prev;
117 }
118