Import of code from c-tap-harness
[openafs.git] / src / external / c-tap-harness / 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, reporting errors, setting
10  * up the TAP output format, or finding things in the test environment.
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, 2011, 2012 Russ Allbery <rra@stanford.edu>
16  * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
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 #include <errno.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #ifdef _WIN32
44 # include <direct.h>
45 #else
46 # include <sys/stat.h>
47 #endif
48 #include <sys/types.h>
49 #include <unistd.h>
50
51 #include <tests/tap/basic.h>
52
53 /* Windows provides mkdir and rmdir under different names. */
54 #ifdef _WIN32
55 # define mkdir(p, m) _mkdir(p)
56 # define rmdir(p)    _rmdir(p)
57 #endif
58
59 /*
60  * The test count.  Always contains the number that will be used for the next
61  * test status.
62  */
63 unsigned long testnum = 1;
64
65 /*
66  * Status information stored so that we can give a test summary at the end of
67  * the test case.  We store the planned final test and the count of failures.
68  * We can get the highest test count from testnum.
69  *
70  * We also store the PID of the process that called plan() and only summarize
71  * results when that process exits, so as to not misreport results in forked
72  * processes.
73  *
74  * If _lazy is true, we're doing lazy planning and will print out the plan
75  * based on the last test number at the end of testing.
76  */
77 static unsigned long _planned = 0;
78 static unsigned long _failed  = 0;
79 static pid_t _process = 0;
80 static int _lazy = 0;
81
82
83 /*
84  * Our exit handler.  Called on completion of the test to report a summary of
85  * results provided we're still in the original process.  This also handles
86  * printing out the plan if we used plan_lazy(), although that's suppressed if
87  * we never ran a test (due to an early bail, for example).
88  */
89 static void
90 finish(void)
91 {
92     unsigned long highest = testnum - 1;
93
94     if (_planned == 0 && !_lazy)
95         return;
96     fflush(stderr);
97     if (_process != 0 && getpid() == _process) {
98         if (_lazy && highest > 0) {
99             printf("1..%lu\n", highest);
100             _planned = highest;
101         }
102         if (_planned > highest)
103             printf("# Looks like you planned %lu test%s but only ran %lu\n",
104                    _planned, (_planned > 1 ? "s" : ""), highest);
105         else if (_planned < highest)
106             printf("# Looks like you planned %lu test%s but ran %lu extra\n",
107                    _planned, (_planned > 1 ? "s" : ""), highest - _planned);
108         else if (_failed > 0)
109             printf("# Looks like you failed %lu test%s of %lu\n", _failed,
110                    (_failed > 1 ? "s" : ""), _planned);
111         else if (_planned > 1)
112             printf("# All %lu tests successful or skipped\n", _planned);
113         else
114             printf("# %lu test successful or skipped\n", _planned);
115     }
116 }
117
118
119 /*
120  * Initialize things.  Turns on line buffering on stdout and then prints out
121  * the number of tests in the test suite.
122  */
123 void
124 plan(unsigned long count)
125 {
126     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
127         fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
128                 strerror(errno));
129     fflush(stderr);
130     printf("1..%lu\n", count);
131     testnum = 1;
132     _planned = count;
133     _process = getpid();
134     atexit(finish);
135 }
136
137
138 /*
139  * Initialize things for lazy planning, where we'll automatically print out a
140  * plan at the end of the program.  Turns on line buffering on stdout as well.
141  */
142 void
143 plan_lazy(void)
144 {
145     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
146         fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
147                 strerror(errno));
148     testnum = 1;
149     _process = getpid();
150     _lazy = 1;
151     atexit(finish);
152 }
153
154
155 /*
156  * Skip the entire test suite and exits.  Should be called instead of plan(),
157  * not after it, since it prints out a special plan line.
158  */
159 void
160 skip_all(const char *format, ...)
161 {
162     fflush(stderr);
163     printf("1..0 # skip");
164     if (format != NULL) {
165         va_list args;
166
167         putchar(' ');
168         va_start(args, format);
169         vprintf(format, args);
170         va_end(args);
171     }
172     putchar('\n');
173     exit(0);
174 }
175
176
177 /*
178  * Print the test description.
179  */
180 static void
181 print_desc(const char *format, va_list args)
182 {
183     printf(" - ");
184     vprintf(format, args);
185 }
186
187
188 /*
189  * Takes a boolean success value and assumes the test passes if that value
190  * is true and fails if that value is false.
191  */
192 void
193 ok(int success, const char *format, ...)
194 {
195     fflush(stderr);
196     printf("%sok %lu", success ? "" : "not ", testnum++);
197     if (!success)
198         _failed++;
199     if (format != NULL) {
200         va_list args;
201
202         va_start(args, format);
203         print_desc(format, args);
204         va_end(args);
205     }
206     putchar('\n');
207 }
208
209
210 /*
211  * Same as ok(), but takes the format arguments as a va_list.
212  */
213 void
214 okv(int success, const char *format, va_list args)
215 {
216     fflush(stderr);
217     printf("%sok %lu", success ? "" : "not ", testnum++);
218     if (!success)
219         _failed++;
220     if (format != NULL)
221         print_desc(format, args);
222     putchar('\n');
223 }
224
225
226 /*
227  * Skip a test.
228  */
229 void
230 skip(const char *reason, ...)
231 {
232     fflush(stderr);
233     printf("ok %lu # skip", testnum++);
234     if (reason != NULL) {
235         va_list args;
236
237         va_start(args, reason);
238         putchar(' ');
239         vprintf(reason, args);
240         va_end(args);
241     }
242     putchar('\n');
243 }
244
245
246 /*
247  * Report the same status on the next count tests.
248  */
249 void
250 ok_block(unsigned long count, int status, const char *format, ...)
251 {
252     unsigned long i;
253
254     fflush(stderr);
255     for (i = 0; i < count; i++) {
256         printf("%sok %lu", status ? "" : "not ", testnum++);
257         if (!status)
258             _failed++;
259         if (format != NULL) {
260             va_list args;
261
262             va_start(args, format);
263             print_desc(format, args);
264             va_end(args);
265         }
266         putchar('\n');
267     }
268 }
269
270
271 /*
272  * Skip the next count tests.
273  */
274 void
275 skip_block(unsigned long count, const char *reason, ...)
276 {
277     unsigned long i;
278
279     fflush(stderr);
280     for (i = 0; i < count; i++) {
281         printf("ok %lu # skip", testnum++);
282         if (reason != NULL) {
283             va_list args;
284
285             va_start(args, reason);
286             putchar(' ');
287             vprintf(reason, args);
288             va_end(args);
289         }
290         putchar('\n');
291     }
292 }
293
294
295 /*
296  * Takes an expected integer and a seen integer and assumes the test passes
297  * if those two numbers match.
298  */
299 void
300 is_int(long wanted, long seen, const char *format, ...)
301 {
302     fflush(stderr);
303     if (wanted == seen)
304         printf("ok %lu", testnum++);
305     else {
306         printf("# wanted: %ld\n#   seen: %ld\n", wanted, seen);
307         printf("not ok %lu", testnum++);
308         _failed++;
309     }
310     if (format != NULL) {
311         va_list args;
312
313         va_start(args, format);
314         print_desc(format, args);
315         va_end(args);
316     }
317     putchar('\n');
318 }
319
320
321 /*
322  * Takes a string and what the string should be, and assumes the test passes
323  * if those strings match (using strcmp).
324  */
325 void
326 is_string(const char *wanted, const char *seen, const char *format, ...)
327 {
328     if (wanted == NULL)
329         wanted = "(null)";
330     if (seen == NULL)
331         seen = "(null)";
332     fflush(stderr);
333     if (strcmp(wanted, seen) == 0)
334         printf("ok %lu", testnum++);
335     else {
336         printf("# wanted: %s\n#   seen: %s\n", wanted, seen);
337         printf("not ok %lu", testnum++);
338         _failed++;
339     }
340     if (format != NULL) {
341         va_list args;
342
343         va_start(args, format);
344         print_desc(format, args);
345         va_end(args);
346     }
347     putchar('\n');
348 }
349
350
351 /*
352  * Takes an expected unsigned long and a seen unsigned long and assumes the
353  * test passes if the two numbers match.  Otherwise, reports them in hex.
354  */
355 void
356 is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
357 {
358     fflush(stderr);
359     if (wanted == seen)
360         printf("ok %lu", testnum++);
361     else {
362         printf("# wanted: %lx\n#   seen: %lx\n", (unsigned long) wanted,
363                (unsigned long) seen);
364         printf("not ok %lu", testnum++);
365         _failed++;
366     }
367     if (format != NULL) {
368         va_list args;
369
370         va_start(args, format);
371         print_desc(format, args);
372         va_end(args);
373     }
374     putchar('\n');
375 }
376
377
378 /*
379  * Bail out with an error.
380  */
381 void
382 bail(const char *format, ...)
383 {
384     va_list args;
385
386     fflush(stderr);
387     fflush(stdout);
388     printf("Bail out! ");
389     va_start(args, format);
390     vprintf(format, args);
391     va_end(args);
392     printf("\n");
393     exit(1);
394 }
395
396
397 /*
398  * Bail out with an error, appending strerror(errno).
399  */
400 void
401 sysbail(const char *format, ...)
402 {
403     va_list args;
404     int oerrno = errno;
405
406     fflush(stderr);
407     fflush(stdout);
408     printf("Bail out! ");
409     va_start(args, format);
410     vprintf(format, args);
411     va_end(args);
412     printf(": %s\n", strerror(oerrno));
413     exit(1);
414 }
415
416
417 /*
418  * Report a diagnostic to stderr.
419  */
420 void
421 diag(const char *format, ...)
422 {
423     va_list args;
424
425     fflush(stderr);
426     fflush(stdout);
427     printf("# ");
428     va_start(args, format);
429     vprintf(format, args);
430     va_end(args);
431     printf("\n");
432 }
433
434
435 /*
436  * Report a diagnostic to stderr, appending strerror(errno).
437  */
438 void
439 sysdiag(const char *format, ...)
440 {
441     va_list args;
442     int oerrno = errno;
443
444     fflush(stderr);
445     fflush(stdout);
446     printf("# ");
447     va_start(args, format);
448     vprintf(format, args);
449     va_end(args);
450     printf(": %s\n", strerror(oerrno));
451 }
452
453
454 /*
455  * Allocate cleared memory, reporting a fatal error with bail on failure.
456  */
457 void *
458 bcalloc(size_t n, size_t size)
459 {
460     void *p;
461
462     p = calloc(n, size);
463     if (p == NULL)
464         sysbail("failed to calloc %lu", (unsigned long)(n * size));
465     return p;
466 }
467
468
469 /*
470  * Allocate memory, reporting a fatal error with bail on failure.
471  */
472 void *
473 bmalloc(size_t size)
474 {
475     void *p;
476
477     p = malloc(size);
478     if (p == NULL)
479         sysbail("failed to malloc %lu", (unsigned long) size);
480     return p;
481 }
482
483
484 /*
485  * Reallocate memory, reporting a fatal error with bail on failure.
486  */
487 void *
488 brealloc(void *p, size_t size)
489 {
490     p = realloc(p, size);
491     if (p == NULL)
492         sysbail("failed to realloc %lu bytes", (unsigned long) size);
493     return p;
494 }
495
496
497 /*
498  * Copy a string, reporting a fatal error with bail on failure.
499  */
500 char *
501 bstrdup(const char *s)
502 {
503     char *p;
504     size_t len;
505
506     len = strlen(s) + 1;
507     p = malloc(len);
508     if (p == NULL)
509         sysbail("failed to strdup %lu bytes", (unsigned long) len);
510     memcpy(p, s, len);
511     return p;
512 }
513
514
515 /*
516  * Copy up to n characters of a string, reporting a fatal error with bail on
517  * failure.  Don't use the system strndup function, since it may not exist and
518  * the TAP library doesn't assume any portability support.
519  */
520 char *
521 bstrndup(const char *s, size_t n)
522 {
523     const char *p;
524     char *copy;
525     size_t length;
526
527     /* Don't assume that the source string is nul-terminated. */
528     for (p = s; (size_t) (p - s) < n && *p != '\0'; p++)
529         ;
530     length = p - s;
531     copy = malloc(length + 1);
532     if (p == NULL)
533         sysbail("failed to strndup %lu bytes", (unsigned long) length);
534     memcpy(copy, s, length);
535     copy[length] = '\0';
536     return copy;
537 }
538
539
540 /*
541  * Locate a test file.  Given the partial path to a file, look under BUILD and
542  * then SOURCE for the file and return the full path to the file.  Returns
543  * NULL if the file doesn't exist.  A non-NULL return should be freed with
544  * test_file_path_free().
545  *
546  * This function uses sprintf because it attempts to be independent of all
547  * other portability layers.  The use immediately after a memory allocation
548  * should be safe without using snprintf or strlcpy/strlcat.
549  */
550 char *
551 test_file_path(const char *file)
552 {
553     char *base;
554     char *path = NULL;
555     size_t length;
556     const char *envs[] = { "BUILD", "SOURCE", NULL };
557     int i;
558
559     for (i = 0; envs[i] != NULL; i++) {
560         base = getenv(envs[i]);
561         if (base == NULL)
562             continue;
563         length = strlen(base) + 1 + strlen(file) + 1;
564         path = bmalloc(length);
565         sprintf(path, "%s/%s", base, file);
566         if (access(path, R_OK) == 0)
567             break;
568         free(path);
569         path = NULL;
570     }
571     return path;
572 }
573
574
575 /*
576  * Free a path returned from test_file_path().  This function exists primarily
577  * for Windows, where memory must be freed from the same library domain that
578  * it was allocated from.
579  */
580 void
581 test_file_path_free(char *path)
582 {
583     if (path != NULL)
584         free(path);
585 }
586
587
588 /*
589  * Create a temporary directory, tmp, under BUILD if set and the current
590  * directory if it does not.  Returns the path to the temporary directory in
591  * newly allocated memory, and calls bail on any failure.  The return value
592  * should be freed with test_tmpdir_free.
593  *
594  * This function uses sprintf because it attempts to be independent of all
595  * other portability layers.  The use immediately after a memory allocation
596  * should be safe without using snprintf or strlcpy/strlcat.
597  */
598 char *
599 test_tmpdir(void)
600 {
601     const char *build;
602     char *path = NULL;
603     size_t length;
604
605     build = getenv("BUILD");
606     if (build == NULL)
607         build = ".";
608     length = strlen(build) + strlen("/tmp") + 1;
609     path = bmalloc(length);
610     sprintf(path, "%s/tmp", build);
611     if (access(path, X_OK) < 0)
612         if (mkdir(path, 0777) < 0)
613             sysbail("error creating temporary directory %s", path);
614     return path;
615 }
616
617
618 /*
619  * Free a path returned from test_tmpdir() and attempt to remove the
620  * directory.  If we can't delete the directory, don't worry; something else
621  * that hasn't yet cleaned up may still be using it.
622  */
623 void
624 test_tmpdir_free(char *path)
625 {
626     rmdir(path);
627     if (path != NULL)
628         free(path);
629 }