]> git.draconx.ca Git - dxcommon.git/blob - src/tap.c
DX_C_ALIGNAS: Work around bash-5 parsing bug.
[dxcommon.git] / src / tap.c
1 /*
2  * Copyright © 2015, 2023 Nick Bowler
3  *
4  * Simple TAP output library for C programs.
5  *
6  * License WTFPL2: Do What The Fuck You Want To Public License, version 2.
7  * This is free software: you are free to do what the fuck you want to.
8  * There is NO WARRANTY, to the extent permitted by law.
9  */
10
11 #if HAVE_CONFIG_H
12 #       include <config.h>
13 #endif
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <assert.h>
18
19 #include "tap.h"
20
21 static unsigned plan, total, passed, xpassed, failed, xfailed;
22
23 void tap_plan(unsigned expected_tests)
24 {
25         if (plan)
26                 tap_bail_out("tap_plan: tests already planned!");
27         if (!expected_tests)
28                 tap_bail_out("tap_plan: no tests to run!");
29
30         plan = expected_tests;
31         printf("1..%u\n", plan);
32 }
33
34 void tap_done(void)
35 {
36         if (!plan) {
37                 tap_plan(total);
38         } else if (total != plan) {
39                 tap_bail_out("tap_done: planned %u tests, ran %u", plan, total);
40         }
41
42         assert(total == passed + xpassed + failed + xfailed);
43         exit(failed || xpassed);
44 }
45
46 void tap_vbail_out(const char *fmt, va_list ap)
47 {
48         printf("Bail out!%*s", fmt != NULL, "");
49         if (fmt)
50                 vprintf(fmt, ap);
51         putchar('\n');
52         exit(99);
53 }
54
55 void tap_bail_out(const char *fmt, ...)
56 {
57         va_list ap;
58
59         va_start(ap, fmt);
60         tap_vbail_out(fmt, ap);
61         va_end(ap);
62 }
63
64 void tap_vskip_all(const char *fmt, va_list ap)
65 {
66         if (plan || total)
67                 tap_bail_out("tap_skip_all: already started tests");
68
69         printf("1..0 # skip%*s", fmt != NULL, "");
70         if (fmt)
71                 vprintf(fmt, ap);
72         putchar('\n');
73         exit(77);
74 }
75
76 void tap_skip_all(const char *fmt, ...)
77 {
78         va_list ap;
79
80         va_start(ap, fmt);
81         tap_vskip_all(fmt, ap);
82         va_end(ap);
83 }
84
85 void tap_vdiag(const char *fmt, va_list ap)
86 {
87         printf("#%*s", fmt != NULL, "");
88         if (fmt)
89                 vprintf(fmt, ap);
90         putchar('\n');
91 }
92
93 void tap_diag(const char *fmt, ...)
94 {
95         va_list ap;
96
97         va_start(ap, fmt);
98         tap_vdiag(fmt, ap);
99         va_end(ap);
100 }
101
102 int tap_vresult(int ok, const char *fmt, va_list ap)
103 {
104         if (!ok)
105                 printf("not ");
106         printf("ok %u%*s", ++total, fmt != NULL, "");
107         if (fmt)
108                 vprintf(fmt, ap);
109         putchar('\n');
110
111         if (!total)
112                 tap_bail_out("cannot handle so many tests");
113
114         passed += !!ok;
115         failed += !ok;
116
117         return ok;
118 }
119
120 int tap_result(int ok, const char *fmt, ...)
121 {
122         va_list ap;
123         int ret;
124
125         va_start(ap, fmt);
126         ret = tap_vresult(ok, fmt, ap);
127         va_end(ap);
128
129         return ret;
130 }