8027a31fd0b3d429318bc42a67b429b22d9d30db
[openafs.git] / tests / tap / basic.c
1 /*
2  * Some utility routines for writing tests.
3  *
4  * Here are a variety of utility routines for writing tests compatible with
5  * the TAP protocol.  All routines of the form ok() or is*() take a test
6  * number and some number of appropriate arguments, check to be sure the
7  * results match the expected output using the arguments, and print out
8  * something appropriate for that test number.  Other utility routines help in
9  * constructing more complex tests, skipping tests, or setting up the TAP
10  * output format.
11  *
12  * This file is part of C TAP Harness.  The current version plus supporting
13  * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
14  *
15  * Copyright 2009, 2010 Russ Allbery <rra@stanford.edu>
16  * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008
17  *     The Board of Trustees of the Leland Stanford Junior University
18  *
19  * Permission is hereby granted, free of charge, to any person obtaining a
20  * copy of this software and associated documentation files (the "Software"),
21  * to deal in the Software without restriction, including without limitation
22  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
23  * and/or sell copies of the Software, and to permit persons to whom the
24  * Software is furnished to do so, subject to the following conditions:
25  *
26  * The above copyright notice and this permission notice shall be included in
27  * all copies or substantial portions of the Software.
28  *
29  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
32  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35  * DEALINGS IN THE SOFTWARE.
36  */
37
38 /* Required for isnan() and isinf(). */
39 #ifndef _XOPEN_SOURCE
40 # define _XOPEN_SOURCE 600
41 #endif
42
43 #include <errno.h>
44 #include <math.h>
45 #include <stdarg.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <sys/types.h>
50 #include <sys/time.h>
51 #include <sys/wait.h>
52 #include <unistd.h>
53
54 #include <tap/basic.h>
55
56 /*
57  * The test count.  Always contains the number that will be used for the next
58  * test status.
59  */
60 unsigned long testnum = 1;
61
62 /*
63  * Status information stored so that we can give a test summary at the end of
64  * the test case.  We store the planned final test and the count of failures.
65  * We can get the highest test count from testnum.
66  *
67  * We also store the PID of the process that called plan() and only summarize
68  * results when that process exits, so as to not misreport results in forked
69  * processes.
70  *
71  * If _lazy is true, we're doing lazy planning and will print out the plan
72  * based on the last test number at the end of testing.
73  */
74 static unsigned long _planned = 0;
75 static unsigned long _failed  = 0;
76 static pid_t _process = 0;
77 static int _lazy = 0;
78
79
80 /*
81  * Our exit handler.  Called on completion of the test to report a summary of
82  * results provided we're still in the original process.
83  */
84 static void
85 finish(void)
86 {
87     unsigned long highest = testnum - 1;
88
89     if (_planned == 0 && !_lazy)
90         return;
91     fflush(stderr);
92     if (_process != 0 && getpid() == _process) {
93         if (_lazy) {
94             printf("1..%lu\n", highest);
95             _planned = highest;
96         }
97         if (_planned > highest)
98             printf("# Looks like you planned %lu test%s but only ran %lu\n",
99                    _planned, (_planned > 1 ? "s" : ""), highest);
100         else if (_planned < highest)
101             printf("# Looks like you planned %lu test%s but ran %lu extra\n",
102                    _planned, (_planned > 1 ? "s" : ""), highest - _planned);
103         else if (_failed > 0)
104             printf("# Looks like you failed %lu test%s of %lu\n", _failed,
105                    (_failed > 1 ? "s" : ""), _planned);
106         else if (_planned > 1)
107             printf("# All %lu tests successful or skipped\n", _planned);
108         else
109             printf("# %lu test successful or skipped\n", _planned);
110     }
111 }
112
113
114 /*
115  * Initialize things.  Turns on line buffering on stdout and then prints out
116  * the number of tests in the test suite.
117  */
118 void
119 plan(unsigned long count)
120 {
121     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
122         fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
123                 strerror(errno));
124     fflush(stderr);
125     printf("1..%lu\n", count);
126     testnum = 1;
127     _planned = count;
128     _process = getpid();
129     atexit(finish);
130 }
131
132
133 /*
134  * Initialize things for lazy planning, where we'll automatically print out a
135  * plan at the end of the program.  Turns on line buffering on stdout as well.
136  */
137 void
138 plan_lazy(void)
139 {
140     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
141         fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
142                 strerror(errno));
143     testnum = 1;
144     _process = getpid();
145     _lazy = 1;
146     atexit(finish);
147 }
148
149
150 /*
151  * Skip the entire test suite and exits.  Should be called instead of plan(),
152  * not after it, since it prints out a special plan line.
153  */
154 void
155 skip_all(const char *format, ...)
156 {
157     fflush(stderr);
158     printf("1..0 # skip");
159     if (format != NULL) {
160         va_list args;
161
162         putchar(' ');
163         va_start(args, format);
164         vprintf(format, args);
165         va_end(args);
166     }
167     putchar('\n');
168     exit(0);
169 }
170
171
172 /*
173  * Print the test description.
174  */
175 static void
176 print_desc(const char *format, va_list args)
177 {
178     printf(" - ");
179     vprintf(format, args);
180 }
181
182
183 /*
184  * Takes a boolean success value and assumes the test passes if that value
185  * is true and fails if that value is false.
186  */
187 void
188 ok(int success, const char *format, ...)
189 {
190     fflush(stderr);
191     printf("%sok %lu", success ? "" : "not ", testnum++);
192     if (!success)
193         _failed++;
194     if (format != NULL) {
195         va_list args;
196
197         va_start(args, format);
198         print_desc(format, args);
199         va_end(args);
200     }
201     putchar('\n');
202 }
203
204
205 /*
206  * Same as ok(), but takes the format arguments as a va_list.
207  */
208 void
209 okv(int success, const char *format, va_list args)
210 {
211     fflush(stderr);
212     printf("%sok %lu", success ? "" : "not ", testnum++);
213     if (!success)
214         _failed++;
215     if (format != NULL)
216         print_desc(format, args);
217     putchar('\n');
218 }
219
220
221 /*
222  * Skip a test.
223  */
224 void
225 skip(const char *reason, ...)
226 {
227     fflush(stderr);
228     printf("ok %lu # skip", testnum++);
229     if (reason != NULL) {
230         va_list args;
231
232         va_start(args, reason);
233         putchar(' ');
234         vprintf(reason, args);
235         va_end(args);
236     }
237     putchar('\n');
238 }
239
240
241 /*
242  * Report the same status on the next count tests.
243  */
244 void
245 ok_block(unsigned long count, int status, const char *format, ...)
246 {
247     unsigned long i;
248
249     fflush(stderr);
250     for (i = 0; i < count; i++) {
251         printf("%sok %lu", status ? "" : "not ", testnum++);
252         if (!status)
253             _failed++;
254         if (format != NULL) {
255             va_list args;
256
257             va_start(args, format);
258             print_desc(format, args);
259             va_end(args);
260         }
261         putchar('\n');
262     }
263 }
264
265
266 /*
267  * Skip the next count tests.
268  */
269 void
270 skip_block(unsigned long count, const char *reason, ...)
271 {
272     unsigned long i;
273
274     fflush(stderr);
275     for (i = 0; i < count; i++) {
276         printf("ok %lu # skip", testnum++);
277         if (reason != NULL) {
278             va_list args;
279
280             va_start(args, reason);
281             putchar(' ');
282             vprintf(reason, args);
283             va_end(args);
284         }
285         putchar('\n');
286     }
287 }
288
289
290 /*
291  * Takes an expected integer and a seen integer and assumes the test passes
292  * if those two numbers match.
293  */
294 void
295 is_int(long wanted, long seen, const char *format, ...)
296 {
297     fflush(stderr);
298     if (wanted == seen)
299         printf("ok %lu", testnum++);
300     else {
301         printf("# wanted: %ld\n#   seen: %ld\n", wanted, seen);
302         printf("not ok %lu", testnum++);
303         _failed++;
304     }
305     if (format != NULL) {
306         va_list args;
307
308         va_start(args, format);
309         print_desc(format, args);
310         va_end(args);
311     }
312     putchar('\n');
313 }
314
315
316 /*
317  * Takes a string and what the string should be, and assumes the test passes
318  * if those strings match (using strcmp).
319  */
320 void
321 is_string(const char *wanted, const char *seen, const char *format, ...)
322 {
323     if (wanted == NULL)
324         wanted = "(null)";
325     if (seen == NULL)
326         seen = "(null)";
327     fflush(stderr);
328     if (strcmp(wanted, seen) == 0)
329         printf("ok %lu", testnum++);
330     else {
331         printf("# wanted: %s\n#   seen: %s\n", wanted, seen);
332         printf("not ok %lu", testnum++);
333         _failed++;
334     }
335     if (format != NULL) {
336         va_list args;
337
338         va_start(args, format);
339         print_desc(format, args);
340         va_end(args);
341     }
342     putchar('\n');
343 }
344
345
346 /*
347  * Takes an expected double and a seen double and assumes the test passes if
348  * those two numbers are within delta of each other.
349  */
350 void
351 is_double(double wanted, double seen, double epsilon, const char *format, ...)
352 {
353     fflush(stderr);
354     if ((isnan(wanted) && isnan(seen))
355         || (isinf(wanted) && isinf(seen) && wanted == seen)
356         || fabs(wanted - seen) <= epsilon)
357         printf("ok %lu", testnum++);
358     else {
359         printf("# wanted: %g\n#   seen: %g\n", wanted, seen);
360         printf("not ok %lu", testnum++);
361         _failed++;
362     }
363     if (format != NULL) {
364         va_list args;
365
366         va_start(args, format);
367         print_desc(format, args);
368         va_end(args);
369     }
370     putchar('\n');
371 }
372
373
374 /*
375  * Takes an expected unsigned long and a seen unsigned long and assumes the
376  * test passes if the two numbers match.  Otherwise, reports them in hex.
377  */
378 void
379 is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
380 {
381     fflush(stderr);
382     if (wanted == seen)
383         printf("ok %lu", testnum++);
384     else {
385         printf("# wanted: %lx\n#   seen: %lx\n", (unsigned long) wanted,
386                (unsigned long) seen);
387         printf("not ok %lu", testnum++);
388         _failed++;
389     }
390     if (format != NULL) {
391         va_list args;
392
393         va_start(args, format);
394         print_desc(format, args);
395         va_end(args);
396     }
397     putchar('\n');
398 }
399
400
401 /*
402  * Bail out with an error.
403  */
404 void
405 bail(const char *format, ...)
406 {
407     va_list args;
408
409     fflush(stderr);
410     fflush(stdout);
411     printf("Bail out! ");
412     va_start(args, format);
413     vprintf(format, args);
414     va_end(args);
415     printf("\n");
416     exit(1);
417 }
418
419
420 /*
421  * Bail out with an error, appending strerror(errno).
422  */
423 void
424 sysbail(const char *format, ...)
425 {
426     va_list args;
427     int oerrno = errno;
428
429     fflush(stderr);
430     fflush(stdout);
431     printf("Bail out! ");
432     va_start(args, format);
433     vprintf(format, args);
434     va_end(args);
435     printf(": %s\n", strerror(oerrno));
436     exit(1);
437 }
438
439
440 /*
441  * Report a diagnostic to stderr.
442  */
443 void
444 diag(const char *format, ...)
445 {
446     va_list args;
447
448     fflush(stderr);
449     fflush(stdout);
450     printf("# ");
451     va_start(args, format);
452     vprintf(format, args);
453     va_end(args);
454     printf("\n");
455 }
456
457
458 /*
459  * Report a diagnostic to stderr, appending strerror(errno).
460  */
461 void
462 sysdiag(const char *format, ...)
463 {
464     va_list args;
465     int oerrno = errno;
466
467     fflush(stderr);
468     fflush(stdout);
469     printf("# ");
470     va_start(args, format);
471     vprintf(format, args);
472     va_end(args);
473     printf(": %s\n", strerror(oerrno));
474 }
475
476
477 /*
478  * Locate a test file.  Given the partial path to a file, look under BUILD and
479  * then SOURCE for the file and return the full path to the file.  Returns
480  * NULL if the file doesn't exist.  A non-NULL return should be freed with
481  * test_file_path_free().
482  *
483  * This function uses sprintf because it attempts to be independent of all
484  * other portability layers.  The use immediately after a memory allocation
485  * should be safe without using snprintf or strlcpy/strlcat.
486  */
487 char *
488 test_file_path(const char *file)
489 {
490     char *base;
491     char *path = NULL;
492     size_t length;
493     const char *envs[] = { "BUILD", "SOURCE", NULL };
494     int i;
495
496     for (i = 0; envs[i] != NULL; i++) {
497         base = getenv(envs[i]);
498         if (base == NULL)
499             continue;
500         length = strlen(base) + 1 + strlen(file) + 1;
501         path = malloc(length);
502         if (path == NULL)
503             sysbail("cannot allocate memory");
504         sprintf(path, "%s/%s", base, file);
505         if (access(path, R_OK) == 0)
506             break;
507         free(path);
508         path = NULL;
509     }
510     return path;
511 }
512
513
514 /*
515  * Free a path returned from test_file_path().  This function exists primarily
516  * for Windows, where memory must be freed from the same library domain that
517  * it was allocated from.
518  */
519 void
520 test_file_path_free(char *path)
521 {
522     if (path != NULL)
523         free(path);
524 }