2cdafa6c7cecf678742f5b4d3feeac88a4bce79a
[openafs.git] / tests / tap / basic.c
1 /*
2  * Some utility routines for writing tests.
3  *
4  * Herein are a variety of utility routines for writing tests.  All routines
5  * of the form ok*() take a test number and some number of appropriate
6  * arguments, check to be sure the results match the expected output using the
7  * arguments, and print out something appropriate for that test number.  Other
8  * utility routines help in constructing more complex tests.
9  *
10  * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
11  * Copyright 2006, 2007, 2008
12  *     Board of Trustees, Leland Stanford Jr. University
13  * Copyright (c) 2004, 2005, 2006
14  *     by Internet Systems Consortium, Inc. ("ISC")
15  * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
16  *     2002, 2003 by The Internet Software Consortium and Rich Salz
17  *
18  * See LICENSE for licensing terms.
19  */
20
21 #include <errno.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30
31 #include <tap/basic.h>
32
33 /*
34  * The test count.  Always contains the number that will be used for the next
35  * test status.
36  */
37 unsigned long testnum = 1;
38
39 /*
40  * Status information stored so that we can give a test summary at the end of
41  * the test case.  We store the planned final test and the count of failures.
42  * We can get the highest test count from testnum.
43  *
44  * We also store the PID of the process that called plan() and only summarize
45  * results when that process exits, so as to not misreport results in forked
46  * processes.
47  *
48  * If _lazy is true, we're doing lazy planning and will print out the plan
49  * based on the last test number at the end of testing.
50  */
51 static unsigned long _planned = 0;
52 static unsigned long _failed  = 0;
53 static pid_t _process = 0;
54 static int _lazy = 0;
55
56
57 /*
58  * Our exit handler.  Called on completion of the test to report a summary of
59  * results provided we're still in the original process.
60  */
61 static void
62 finish(void)
63 {
64     unsigned long highest = testnum - 1;
65
66     if (_planned == 0 && !_lazy)
67         return;
68     if (_process != 0 && getpid() == _process) {
69         if (_lazy) {
70             printf("1..%lu\n", highest);
71             _planned = highest;
72         }
73         if (_planned > highest)
74             printf("# Looks like you planned %lu test%s but only ran %lu\n",
75                    _planned, (_planned > 1 ? "s" : ""), highest);
76         else if (_planned < highest)
77             printf("# Looks like you planned %lu test%s but ran %lu extra\n",
78                    _planned, (_planned > 1 ? "s" : ""), highest - _planned);
79         else if (_failed > 0)
80             printf("# Looks like you failed %lu test%s of %lu\n", _failed,
81                    (_failed > 1 ? "s" : ""), _planned);
82         else if (_planned > 1)
83             printf("# All %lu tests successful or skipped\n", _planned);
84         else
85             printf("# %lu test successful or skipped\n", _planned);
86     }
87 }
88
89
90 /*
91  * Initialize things.  Turns on line buffering on stdout and then prints out
92  * the number of tests in the test suite.
93  */
94 void
95 plan(unsigned long count)
96 {
97     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
98         fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
99                 strerror(errno));
100     printf("1..%lu\n", count);
101     testnum = 1;
102     _planned = count;
103     _process = getpid();
104     atexit(finish);
105 }
106
107
108 /*
109  * Initialize things for lazy planning, where we'll automatically print out a
110  * plan at the end of the program.  Turns on line buffering on stdout as well.
111  */
112 void
113 plan_lazy(void)
114 {
115     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
116         fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
117                 strerror(errno));
118     testnum = 1;
119     _process = getpid();
120     _lazy = 1;
121     atexit(finish);
122 }
123
124
125 /*
126  * Skip the entire test suite and exits.  Should be called instead of plan(),
127  * not after it, since it prints out a special plan line.
128  */
129 void
130 skip_all(const char *format, ...)
131 {
132     printf("1..0 # skip");
133     if (format != NULL) {
134         va_list args;
135
136         putchar(' ');
137         va_start(args, format);
138         vprintf(format, args);
139         va_end(args);
140     }
141     putchar('\n');
142     exit(0);
143 }
144
145
146 /*
147  * Print the test description.
148  */
149 static void
150 print_desc(const char *format, va_list args)
151 {
152     printf(" - ");
153     vprintf(format, args);
154 }
155
156
157 /*
158  * Takes a boolean success value and assumes the test passes if that value
159  * is true and fails if that value is false.
160  */
161 void
162 ok(int success, const char *format, ...)
163 {
164     printf("%sok %lu", success ? "" : "not ", testnum++);
165     if (!success)
166         _failed++;
167     if (format != NULL) {
168         va_list args;
169
170         va_start(args, format);
171         print_desc(format, args);
172         va_end(args);
173     }
174     putchar('\n');
175 }
176
177
178 /*
179  * Skip a test.
180  */
181 void
182 skip(const char *reason, ...)
183 {
184     printf("ok %lu # skip", testnum++);
185     if (reason != NULL) {
186         va_list args;
187
188         va_start(args, reason);
189         putchar(' ');
190         vprintf(reason, args);
191         va_end(args);
192     }
193     putchar('\n');
194 }
195
196
197 /*
198  * Report the same status on the next count tests.
199  */
200 void
201 ok_block(unsigned long count, int status, const char *format, ...)
202 {
203     unsigned long i;
204
205     for (i = 0; i < count; i++) {
206         printf("%sok %lu", status ? "" : "not ", testnum++);
207         if (!status)
208             _failed++;
209         if (format != NULL) {
210             va_list args;
211
212             va_start(args, format);
213             print_desc(format, args);
214             va_end(args);
215         }
216         putchar('\n');
217     }
218 }
219
220
221 /*
222  * Skip the next count tests.
223  */
224 void
225 skip_block(unsigned long count, const char *reason, ...)
226 {
227     unsigned long i;
228
229     for (i = 0; i < count; i++) {
230         printf("ok %lu # skip", testnum++);
231         if (reason != NULL) {
232             va_list args;
233
234             va_start(args, reason);
235             putchar(' ');
236             vprintf(reason, args);
237             va_end(args);
238         }
239         putchar('\n');
240     }
241 }
242
243
244 /*
245  * Takes an expected integer and a seen integer and assumes the test passes
246  * if those two numbers match.
247  */
248 void
249 is_int(long wanted, long seen, const char *format, ...)
250 {
251     if (wanted == seen)
252         printf("ok %lu", testnum++);
253     else {
254         printf("# wanted: %ld\n#   seen: %ld\n", wanted, seen);
255         printf("not ok %lu", testnum++);
256         _failed++;
257     }
258     if (format != NULL) {
259         va_list args;
260
261         va_start(args, format);
262         print_desc(format, args);
263         va_end(args);
264     }
265     putchar('\n');
266 }
267
268
269 /*
270  * Takes a string and what the string should be, and assumes the test passes
271  * if those strings match (using strcmp).
272  */
273 void
274 is_string(const char *wanted, const char *seen, const char *format, ...)
275 {
276     if (wanted == NULL)
277         wanted = "(null)";
278     if (seen == NULL)
279         seen = "(null)";
280     if (strcmp(wanted, seen) == 0)
281         printf("ok %lu", testnum++);
282     else {
283         printf("# wanted: %s\n#   seen: %s\n", wanted, seen);
284         printf("not ok %lu", testnum++);
285         _failed++;
286     }
287     if (format != NULL) {
288         va_list args;
289
290         va_start(args, format);
291         print_desc(format, args);
292         va_end(args);
293     }
294     putchar('\n');
295 }
296
297
298 /*
299  * Takes an expected double and a seen double and assumes the test passes if
300  * those two numbers match.
301  */
302 void
303 is_double(double wanted, double seen, const char *format, ...)
304 {
305     if (wanted == seen)
306         printf("ok %lu", testnum++);
307     else {
308         printf("# wanted: %g\n#   seen: %g\n", wanted, seen);
309         printf("not ok %lu", testnum++);
310         _failed++;
311     }
312     if (format != NULL) {
313         va_list args;
314
315         va_start(args, format);
316         print_desc(format, args);
317         va_end(args);
318     }
319     putchar('\n');
320 }
321
322
323 /*
324  * Takes an expected unsigned long and a seen unsigned long and assumes the
325  * test passes if the two numbers match.  Otherwise, reports them in hex.
326  */
327 void
328 is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
329 {
330     if (wanted == seen)
331         printf("ok %lu", testnum++);
332     else {
333         printf("# wanted: %lx\n#   seen: %lx\n", (unsigned long) wanted,
334                (unsigned long) seen);
335         printf("not ok %lu", testnum++);
336         _failed++;
337     }
338     if (format != NULL) {
339         va_list args;
340
341         va_start(args, format);
342         print_desc(format, args);
343         va_end(args);
344     }
345     putchar('\n');
346 }
347
348
349 /*
350  * Bail out with an error.
351  */
352 void
353 bail(const char *format, ...)
354 {
355     va_list args;
356
357     fflush(stdout);
358     printf("Bail out! ");
359     va_start(args, format);
360     vprintf(format, args);
361     va_end(args);
362     printf("\n");
363     exit(1);
364 }
365
366
367 /*
368  * Bail out with an error, appending strerror(errno).
369  */
370 void
371 sysbail(const char *format, ...)
372 {
373     va_list args;
374     int oerrno = errno;
375
376     fflush(stdout);
377     printf("Bail out! ");
378     va_start(args, format);
379     vprintf(format, args);
380     va_end(args);
381     printf(": %s\n", strerror(oerrno));
382     exit(1);
383 }
384
385
386 /*
387  * Report a diagnostic to stderr.
388  */
389 void
390 diag(const char *format, ...)
391 {
392     va_list args;
393
394     fflush(stdout);
395     printf("# ");
396     va_start(args, format);
397     vprintf(format, args);
398     va_end(args);
399     printf("\n");
400 }
401
402
403 /*
404  * Report a diagnostic to stderr, appending strerror(errno).
405  */
406 void
407 sysdiag(const char *format, ...)
408 {
409     va_list args;
410     int oerrno = errno;
411
412     fflush(stdout);
413     printf("# ");
414     va_start(args, format);
415     vprintf(format, args);
416     va_end(args);
417     printf(": %s\n", strerror(oerrno));
418 }