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