Add okv function to the TAP test library
[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  * Same as ok(), but takes the format arguments as a va_list.
180  */
181 void
182 okv(int success, const char *format, va_list args)
183 {
184     printf("%sok %lu", success ? "" : "not ", testnum++);
185     if (!success)
186         _failed++;
187     if (format != NULL)
188         print_desc(format, args);
189     putchar('\n');
190 }
191
192
193 /*
194  * Skip a test.
195  */
196 void
197 skip(const char *reason, ...)
198 {
199     printf("ok %lu # skip", testnum++);
200     if (reason != NULL) {
201         va_list args;
202
203         va_start(args, reason);
204         putchar(' ');
205         vprintf(reason, args);
206         va_end(args);
207     }
208     putchar('\n');
209 }
210
211
212 /*
213  * Report the same status on the next count tests.
214  */
215 void
216 ok_block(unsigned long count, int status, const char *format, ...)
217 {
218     unsigned long i;
219
220     for (i = 0; i < count; i++) {
221         printf("%sok %lu", status ? "" : "not ", testnum++);
222         if (!status)
223             _failed++;
224         if (format != NULL) {
225             va_list args;
226
227             va_start(args, format);
228             print_desc(format, args);
229             va_end(args);
230         }
231         putchar('\n');
232     }
233 }
234
235
236 /*
237  * Skip the next count tests.
238  */
239 void
240 skip_block(unsigned long count, const char *reason, ...)
241 {
242     unsigned long i;
243
244     for (i = 0; i < count; i++) {
245         printf("ok %lu # skip", testnum++);
246         if (reason != NULL) {
247             va_list args;
248
249             va_start(args, reason);
250             putchar(' ');
251             vprintf(reason, args);
252             va_end(args);
253         }
254         putchar('\n');
255     }
256 }
257
258
259 /*
260  * Takes an expected integer and a seen integer and assumes the test passes
261  * if those two numbers match.
262  */
263 void
264 is_int(long wanted, long seen, const char *format, ...)
265 {
266     if (wanted == seen)
267         printf("ok %lu", testnum++);
268     else {
269         printf("# wanted: %ld\n#   seen: %ld\n", wanted, seen);
270         printf("not ok %lu", testnum++);
271         _failed++;
272     }
273     if (format != NULL) {
274         va_list args;
275
276         va_start(args, format);
277         print_desc(format, args);
278         va_end(args);
279     }
280     putchar('\n');
281 }
282
283
284 /*
285  * Takes a string and what the string should be, and assumes the test passes
286  * if those strings match (using strcmp).
287  */
288 void
289 is_string(const char *wanted, const char *seen, const char *format, ...)
290 {
291     if (wanted == NULL)
292         wanted = "(null)";
293     if (seen == NULL)
294         seen = "(null)";
295     if (strcmp(wanted, seen) == 0)
296         printf("ok %lu", testnum++);
297     else {
298         printf("# wanted: %s\n#   seen: %s\n", wanted, seen);
299         printf("not ok %lu", testnum++);
300         _failed++;
301     }
302     if (format != NULL) {
303         va_list args;
304
305         va_start(args, format);
306         print_desc(format, args);
307         va_end(args);
308     }
309     putchar('\n');
310 }
311
312
313 /*
314  * Takes an expected double and a seen double and assumes the test passes if
315  * those two numbers match.
316  */
317 void
318 is_double(double wanted, double seen, const char *format, ...)
319 {
320     if (wanted == seen)
321         printf("ok %lu", testnum++);
322     else {
323         printf("# wanted: %g\n#   seen: %g\n", wanted, seen);
324         printf("not ok %lu", testnum++);
325         _failed++;
326     }
327     if (format != NULL) {
328         va_list args;
329
330         va_start(args, format);
331         print_desc(format, args);
332         va_end(args);
333     }
334     putchar('\n');
335 }
336
337
338 /*
339  * Takes an expected unsigned long and a seen unsigned long and assumes the
340  * test passes if the two numbers match.  Otherwise, reports them in hex.
341  */
342 void
343 is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
344 {
345     if (wanted == seen)
346         printf("ok %lu", testnum++);
347     else {
348         printf("# wanted: %lx\n#   seen: %lx\n", (unsigned long) wanted,
349                (unsigned long) seen);
350         printf("not ok %lu", testnum++);
351         _failed++;
352     }
353     if (format != NULL) {
354         va_list args;
355
356         va_start(args, format);
357         print_desc(format, args);
358         va_end(args);
359     }
360     putchar('\n');
361 }
362
363
364 /*
365  * Bail out with an error.
366  */
367 void
368 bail(const char *format, ...)
369 {
370     va_list args;
371
372     fflush(stdout);
373     printf("Bail out! ");
374     va_start(args, format);
375     vprintf(format, args);
376     va_end(args);
377     printf("\n");
378     exit(1);
379 }
380
381
382 /*
383  * Bail out with an error, appending strerror(errno).
384  */
385 void
386 sysbail(const char *format, ...)
387 {
388     va_list args;
389     int oerrno = errno;
390
391     fflush(stdout);
392     printf("Bail out! ");
393     va_start(args, format);
394     vprintf(format, args);
395     va_end(args);
396     printf(": %s\n", strerror(oerrno));
397     exit(1);
398 }
399
400
401 /*
402  * Report a diagnostic to stderr.
403  */
404 void
405 diag(const char *format, ...)
406 {
407     va_list args;
408
409     fflush(stdout);
410     printf("# ");
411     va_start(args, format);
412     vprintf(format, args);
413     va_end(args);
414     printf("\n");
415 }
416
417
418 /*
419  * Report a diagnostic to stderr, appending strerror(errno).
420  */
421 void
422 sysdiag(const char *format, ...)
423 {
424     va_list args;
425     int oerrno = errno;
426
427     fflush(stdout);
428     printf("# ");
429     va_start(args, format);
430     vprintf(format, args);
431     va_end(args);
432     printf(": %s\n", strerror(oerrno));
433 }