]> jfr.im git - solanum.git/blame - tests/tap/basic.c
callerid: actually the guard should be for source_p
[solanum.git] / tests / tap / basic.c
CommitLineData
8fe5ef5a
SA
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 <https://www.eyrie.org/~eagle/software/c-tap-harness/>.
14 *
15 * Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016
16 * Russ Allbery <eagle@eyrie.org>
17 * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012, 2013, 2014
18 * The Board of Trustees of the Leland Stanford Junior University
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a
21 * copy of this software and associated documentation files (the "Software"),
22 * to deal in the Software without restriction, including without limitation
23 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 * and/or sell copies of the Software, and to permit persons to whom the
25 * Software is furnished to do so, subject to the following conditions:
26 *
27 * The above copyright notice and this permission notice shall be included in
28 * all copies or substantial portions of the Software.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
33 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36 * DEALINGS IN THE SOFTWARE.
37 */
38
39#include <errno.h>
40#include <limits.h>
41#include <stdarg.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#ifdef _WIN32
46# include <direct.h>
47#else
48# include <sys/stat.h>
49#endif
50#include <sys/types.h>
51#include <unistd.h>
52
53#include <tests/tap/basic.h>
54
55/* Windows provides mkdir and rmdir under different names. */
56#ifdef _WIN32
57# define mkdir(p, m) _mkdir(p)
58# define rmdir(p) _rmdir(p)
59#endif
60
61/*
62 * The test count. Always contains the number that will be used for the next
63 * test status. This is exported to callers of the library.
64 */
65unsigned long testnum = 1;
66
67/*
68 * Status information stored so that we can give a test summary at the end of
69 * the test case. We store the planned final test and the count of failures.
70 * We can get the highest test count from testnum.
71 */
72static unsigned long _planned = 0;
73static unsigned long _failed = 0;
74
75/*
76 * Store the PID of the process that called plan() and only summarize
77 * results when that process exits, so as to not misreport results in forked
78 * processes.
79 */
80static pid_t _process = 0;
81
82/*
83 * If true, we're doing lazy planning and will print out the plan based on the
84 * last test number at the end of testing.
85 */
86static int _lazy = 0;
87
88/*
89 * If true, the test was aborted by calling bail(). Currently, this is only
90 * used to ensure that we pass a false value to any cleanup functions even if
91 * all tests to that point have passed.
92 */
93static int _aborted = 0;
94
95/*
96 * Registered cleanup functions. These are stored as a linked list and run in
97 * registered order by finish when the test program exits. Each function is
98 * passed a boolean value indicating whether all tests were successful.
99 */
100struct cleanup_func {
101 test_cleanup_func func;
102 struct cleanup_func *next;
103};
104static struct cleanup_func *cleanup_funcs = NULL;
105
106/*
107 * Registered diag files. Any output found in these files will be printed out
108 * as if it were passed to diag() before any other output we do. This allows
109 * background processes to log to a file and have that output interleaved with
110 * the test output.
111 */
112struct diag_file {
113 char *name;
114 FILE *file;
115 char *buffer;
116 size_t bufsize;
117 struct diag_file *next;
118};
119static struct diag_file *diag_files = NULL;
120
121/*
122 * Print a specified prefix and then the test description. Handles turning
123 * the argument list into a va_args structure suitable for passing to
124 * print_desc, which has to be done in a macro. Assumes that format is the
125 * argument immediately before the variadic arguments.
126 */
127#define PRINT_DESC(prefix, format) \
128 do { \
129 if (format != NULL) { \
130 va_list args; \
131 if (prefix != NULL) \
132 printf("%s", prefix); \
133 va_start(args, format); \
134 vprintf(format, args); \
135 va_end(args); \
136 } \
137 } while (0)
138
139
140/*
141 * Form a new string by concatenating multiple strings. The arguments must be
142 * terminated by (const char *) 0.
143 *
144 * This function only exists because we can't assume asprintf. We can't
145 * simulate asprintf with snprintf because we're only assuming SUSv3, which
146 * does not require that snprintf with a NULL buffer return the required
147 * length. When those constraints are relaxed, this should be ripped out and
148 * replaced with asprintf or a more trivial replacement with snprintf.
149 */
150static char *
151concat(const char *first, ...)
152{
153 va_list args;
154 char *result;
155 const char *string;
156 size_t offset;
157 size_t length = 0;
158
159 /*
160 * Find the total memory required. Ensure we don't overflow length. See
161 * the comment for breallocarray for why we're using UINT_MAX here.
162 */
163 va_start(args, first);
164 for (string = first; string != NULL; string = va_arg(args, const char *)) {
165 if (length >= UINT_MAX - strlen(string))
166 bail("strings too long in concat");
167 length += strlen(string);
168 }
169 va_end(args);
170 length++;
171
172 /* Create the string. */
173 result = bmalloc(length);
174 va_start(args, first);
175 offset = 0;
176 for (string = first; string != NULL; string = va_arg(args, const char *)) {
177 memcpy(result + offset, string, strlen(string));
178 offset += strlen(string);
179 }
180 va_end(args);
181 result[offset] = '\0';
182 return result;
183}
184
185
186/*
187 * Check all registered diag_files for any output. We only print out the
188 * output if we see a complete line; otherwise, we wait for the next newline.
189 */
190static void
191check_diag_files(void)
192{
193 struct diag_file *file;
194 fpos_t where;
195 size_t length;
196 int size, incomplete;
197
198 /*
199 * Walk through each file and read each line of output available. The
200 * general scheme here used is as follows: try to read a line of output at
201 * a time. If we get NULL, check for EOF; on EOF, advance to the next
202 * file.
203 *
204 * If we get some data, see if it ends in a newline. If it doesn't end in
205 * a newline, we have one of two cases: our buffer isn't large enough, in
206 * which case we resize it and try again, or we have incomplete data in
207 * the file, in which case we rewind the file and will try again next
208 * time.
209 */
210 for (file = diag_files; file != NULL; file = file->next) {
211 clearerr(file->file);
212
213 /* Store the current position in case we have to rewind. */
214 if (fgetpos(file->file, &where) < 0)
215 sysbail("cannot get position in %s", file->name);
216
217 /* Continue until we get EOF or an incomplete line of data. */
218 incomplete = 0;
219 while (!feof(file->file) && !incomplete) {
220 size = file->bufsize > INT_MAX ? INT_MAX : (int) file->bufsize;
221 if (fgets(file->buffer, size, file->file) == NULL) {
222 if (ferror(file->file))
223 sysbail("cannot read from %s", file->name);
224 continue;
225 }
226
227 /*
228 * See if the line ends in a newline. If not, see which error
229 * case we have. Use UINT_MAX as a substitute for SIZE_MAX (see
230 * the comment for breallocarray).
231 */
232 length = strlen(file->buffer);
233 if (file->buffer[length - 1] != '\n') {
234 if (length < file->bufsize - 1)
235 incomplete = 1;
236 else {
237 if (file->bufsize >= UINT_MAX - BUFSIZ)
238 sysbail("line too long in %s", file->name);
239 file->bufsize += BUFSIZ;
240 file->buffer = brealloc(file->buffer, file->bufsize);
241 }
242
243 /*
244 * On either incomplete lines or too small of a buffer, rewind
245 * and read the file again (on the next pass, if incomplete).
246 * It's simpler than trying to double-buffer the file.
247 */
248 if (fsetpos(file->file, &where) < 0)
249 sysbail("cannot set position in %s", file->name);
250 continue;
251 }
252
253 /* We saw a complete line. Print it out. */
254 printf("# %s", file->buffer);
255 }
256 }
257}
258
259
260/*
261 * Our exit handler. Called on completion of the test to report a summary of
262 * results provided we're still in the original process. This also handles
263 * printing out the plan if we used plan_lazy(), although that's suppressed if
264 * we never ran a test (due to an early bail, for example), and running any
265 * registered cleanup functions.
266 */
267static void
268finish(void)
269{
270 int success, primary;
271 struct cleanup_func *current;
272 unsigned long highest = testnum - 1;
273 struct diag_file *file, *tmp;
274
275 /* Check for pending diag_file output. */
276 check_diag_files();
277
278 /* Free the diag_files. */
279 file = diag_files;
280 while (file != NULL) {
281 tmp = file;
282 file = file->next;
283 fclose(tmp->file);
284 free(tmp->name);
285 free(tmp->buffer);
286 free(tmp);
287 }
288 diag_files = NULL;
289
290 /*
291 * Determine whether all tests were successful, which is needed before
292 * calling cleanup functions since we pass that fact to the functions.
293 */
294 if (_planned == 0 && _lazy)
295 _planned = highest;
296 success = (!_aborted && _planned == highest && _failed == 0);
297
298 /*
299 * If there are any registered cleanup functions, we run those first. We
300 * always run them, even if we didn't run a test. Don't do anything
301 * except free the diag_files and call cleanup functions if we aren't the
302 * primary process (the process in which plan or plan_lazy was called),
303 * and tell the cleanup functions that fact.
304 */
305 primary = (_process == 0 || getpid() == _process);
306 while (cleanup_funcs != NULL) {
307 cleanup_funcs->func(success, primary);
308 current = cleanup_funcs;
309 cleanup_funcs = cleanup_funcs->next;
310 free(current);
311 }
312 if (!primary)
313 return;
314
315 /* Don't do anything further if we never planned a test. */
316 if (_planned == 0)
317 return;
318
319 /* If we're aborting due to bail, don't print summaries. */
320 if (_aborted)
321 return;
322
323 /* Print out the lazy plan if needed. */
324 fflush(stderr);
325 if (_lazy && _planned > 0)
326 printf("1..%lu\n", _planned);
327
328 /* Print out a summary of the results. */
329 if (_planned > highest)
330 diag("Looks like you planned %lu test%s but only ran %lu", _planned,
331 (_planned > 1 ? "s" : ""), highest);
332 else if (_planned < highest)
333 diag("Looks like you planned %lu test%s but ran %lu extra", _planned,
334 (_planned > 1 ? "s" : ""), highest - _planned);
335 else if (_failed > 0)
336 diag("Looks like you failed %lu test%s of %lu", _failed,
337 (_failed > 1 ? "s" : ""), _planned);
338 else if (_planned != 1)
339 diag("All %lu tests successful or skipped", _planned);
340 else
341 diag("%lu test successful or skipped", _planned);
342}
343
344
345/*
346 * Initialize things. Turns on line buffering on stdout and then prints out
347 * the number of tests in the test suite. We intentionally don't check for
348 * pending diag_file output here, since it should really come after the plan.
349 */
350void
351plan(unsigned long count)
352{
353 if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
354 sysdiag("cannot set stdout to line buffered");
355 fflush(stderr);
356 printf("1..%lu\n", count);
357 testnum = 1;
358 _planned = count;
359 _process = getpid();
360 if (atexit(finish) != 0) {
361 sysdiag("cannot register exit handler");
362 diag("cleanups will not be run");
363 }
364}
365
366
367/*
368 * Initialize things for lazy planning, where we'll automatically print out a
369 * plan at the end of the program. Turns on line buffering on stdout as well.
370 */
371void
372plan_lazy(void)
373{
374 if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
375 sysdiag("cannot set stdout to line buffered");
376 testnum = 1;
377 _process = getpid();
378 _lazy = 1;
379 if (atexit(finish) != 0)
380 sysbail("cannot register exit handler to display plan");
381}
382
383
384/*
385 * Skip the entire test suite and exits. Should be called instead of plan(),
386 * not after it, since it prints out a special plan line. Ignore diag_file
387 * output here, since it's not clear if it's allowed before the plan.
388 */
389void
390skip_all(const char *format, ...)
391{
392 fflush(stderr);
393 printf("1..0 # skip");
394 PRINT_DESC(" ", format);
395 putchar('\n');
396 exit(0);
397}
398
399
400/*
401 * Takes a boolean success value and assumes the test passes if that value
402 * is true and fails if that value is false.
403 */
404int
405ok(int success, const char *format, ...)
406{
407 fflush(stderr);
408 check_diag_files();
409 printf("%sok %lu", success ? "" : "not ", testnum++);
410 if (!success)
411 _failed++;
412 PRINT_DESC(" - ", format);
413 putchar('\n');
414 return success;
415}
416
417
418/*
419 * Same as ok(), but takes the format arguments as a va_list.
420 */
421int
422okv(int success, const char *format, va_list args)
423{
424 fflush(stderr);
425 check_diag_files();
426 printf("%sok %lu", success ? "" : "not ", testnum++);
427 if (!success)
428 _failed++;
429 if (format != NULL) {
430 printf(" - ");
431 vprintf(format, args);
432 }
433 putchar('\n');
434 return success;
435}
436
437
438/*
439 * Skip a test.
440 */
441void
442skip(const char *reason, ...)
443{
444 fflush(stderr);
445 check_diag_files();
446 printf("ok %lu # skip", testnum++);
447 PRINT_DESC(" ", reason);
448 putchar('\n');
449}
450
451
452/*
453 * Report the same status on the next count tests.
454 */
455int
456ok_block(unsigned long count, int success, const char *format, ...)
457{
458 unsigned long i;
459
460 fflush(stderr);
461 check_diag_files();
462 for (i = 0; i < count; i++) {
463 printf("%sok %lu", success ? "" : "not ", testnum++);
464 if (!success)
465 _failed++;
466 PRINT_DESC(" - ", format);
467 putchar('\n');
468 }
469 return success;
470}
471
472
473/*
474 * Skip the next count tests.
475 */
476void
477skip_block(unsigned long count, const char *reason, ...)
478{
479 unsigned long i;
480
481 fflush(stderr);
482 check_diag_files();
483 for (i = 0; i < count; i++) {
484 printf("ok %lu # skip", testnum++);
485 PRINT_DESC(" ", reason);
486 putchar('\n');
487 }
488}
489
490
491/*
492 * Takes an expected boolean value and a seen boolean value and assumes the
493 * test passes if the truth value of both match.
494 */
495int
496is_bool(int wanted, int seen, const char *format, ...)
497{
498 int success;
499
500 fflush(stderr);
501 check_diag_files();
502 success = (!!wanted == !!seen);
503 if (success)
504 printf("ok %lu", testnum++);
505 else {
506 diag("wanted: %s", !!wanted ? "true" : "false");
507 diag(" seen: %s", !!seen ? "true" : "false");
508 printf("not ok %lu", testnum++);
509 _failed++;
510 }
511 PRINT_DESC(" - ", format);
512 putchar('\n');
513 return success;
514}
515
516
517/*
518 * Takes an expected integer and a seen integer and assumes the test passes
519 * if those two numbers match.
520 */
521int
522is_int(long wanted, long seen, const char *format, ...)
523{
524 int success;
525
526 fflush(stderr);
527 check_diag_files();
528 success = (wanted == seen);
529 if (success)
530 printf("ok %lu", testnum++);
531 else {
532 diag("wanted: %ld", wanted);
533 diag(" seen: %ld", seen);
534 printf("not ok %lu", testnum++);
535 _failed++;
536 }
537 PRINT_DESC(" - ", format);
538 putchar('\n');
539 return success;
540}
541
542
543/*
544 * Takes a string and what the string should be, and assumes the test passes
545 * if those strings match (using strcmp).
546 */
547int
548is_string(const char *wanted, const char *seen, const char *format, ...)
549{
550 int success;
551
552 if (wanted == NULL)
553 wanted = "(null)";
554 if (seen == NULL)
555 seen = "(null)";
556 fflush(stderr);
557 check_diag_files();
558 success = (strcmp(wanted, seen) == 0);
559 if (success)
560 printf("ok %lu", testnum++);
561 else {
562 diag("wanted: %s", wanted);
563 diag(" seen: %s", seen);
564 printf("not ok %lu", testnum++);
565 _failed++;
566 }
567 PRINT_DESC(" - ", format);
568 putchar('\n');
569 return success;
570}
571
572
573/*
574 * Takes an expected unsigned long and a seen unsigned long and assumes the
575 * test passes if the two numbers match. Otherwise, reports them in hex.
576 */
577int
578is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
579{
580 int success;
581
582 fflush(stderr);
583 check_diag_files();
584 success = (wanted == seen);
585 if (success)
586 printf("ok %lu", testnum++);
587 else {
588 diag("wanted: %lx", (unsigned long) wanted);
589 diag(" seen: %lx", (unsigned long) seen);
590 printf("not ok %lu", testnum++);
591 _failed++;
592 }
593 PRINT_DESC(" - ", format);
594 putchar('\n');
595 return success;
596}
597
598
599/*
600 * Bail out with an error.
601 */
602void
603bail(const char *format, ...)
604{
605 va_list args;
606
607 _aborted = 1;
608 fflush(stderr);
609 check_diag_files();
610 fflush(stdout);
611 printf("Bail out! ");
612 va_start(args, format);
613 vprintf(format, args);
614 va_end(args);
615 printf("\n");
616 exit(255);
617}
618
619
620/*
621 * Bail out with an error, appending strerror(errno).
622 */
623void
624sysbail(const char *format, ...)
625{
626 va_list args;
627 int oerrno = errno;
628
629 _aborted = 1;
630 fflush(stderr);
631 check_diag_files();
632 fflush(stdout);
633 printf("Bail out! ");
634 va_start(args, format);
635 vprintf(format, args);
636 va_end(args);
637 printf(": %s\n", strerror(oerrno));
638 exit(255);
639}
640
641
642/*
643 * Report a diagnostic to stderr. Always returns 1 to allow embedding in
644 * compound statements.
645 */
646int
647diag(const char *format, ...)
648{
649 va_list args;
650
651 fflush(stderr);
652 check_diag_files();
653 fflush(stdout);
654 printf("# ");
655 va_start(args, format);
656 vprintf(format, args);
657 va_end(args);
658 printf("\n");
659 return 1;
660}
661
662
663/*
664 * Report a diagnostic to stderr, appending strerror(errno). Always returns 1
665 * to allow embedding in compound statements.
666 */
667int
668sysdiag(const char *format, ...)
669{
670 va_list args;
671 int oerrno = errno;
672
673 fflush(stderr);
674 check_diag_files();
675 fflush(stdout);
676 printf("# ");
677 va_start(args, format);
678 vprintf(format, args);
679 va_end(args);
680 printf(": %s\n", strerror(oerrno));
681 return 1;
682}
683
684
685/*
686 * Register a new file for diag_file processing.
687 */
688void
689diag_file_add(const char *name)
690{
691 struct diag_file *file, *prev;
692
693 file = bcalloc(1, sizeof(struct diag_file));
694 file->name = bstrdup(name);
695 file->file = fopen(file->name, "r");
696 if (file->file == NULL)
697 sysbail("cannot open %s", name);
698 file->buffer = bmalloc(BUFSIZ);
699 file->bufsize = BUFSIZ;
700 if (diag_files == NULL)
701 diag_files = file;
702 else {
703 for (prev = diag_files; prev->next != NULL; prev = prev->next)
704 ;
705 prev->next = file;
706 }
707}
708
709
710/*
711 * Remove a file from diag_file processing. If the file is not found, do
712 * nothing, since there are some situations where it can be removed twice
713 * (such as if it's removed from a cleanup function, since cleanup functions
714 * are called after freeing all the diag_files).
715 */
716void
717diag_file_remove(const char *name)
718{
719 struct diag_file *file;
720 struct diag_file **prev = &diag_files;
721
722 for (file = diag_files; file != NULL; file = file->next) {
723 if (strcmp(file->name, name) == 0) {
724 *prev = file->next;
725 fclose(file->file);
726 free(file->name);
727 free(file->buffer);
728 free(file);
729 return;
730 }
731 prev = &file->next;
732 }
733}
734
735
736/*
737 * Allocate cleared memory, reporting a fatal error with bail on failure.
738 */
739void *
740bcalloc(size_t n, size_t size)
741{
742 void *p;
743
744 p = calloc(n, size);
745 if (p == NULL)
746 sysbail("failed to calloc %lu", (unsigned long)(n * size));
747 return p;
748}
749
750
751/*
752 * Allocate memory, reporting a fatal error with bail on failure.
753 */
754void *
755bmalloc(size_t size)
756{
757 void *p;
758
759 p = malloc(size);
760 if (p == NULL)
761 sysbail("failed to malloc %lu", (unsigned long) size);
762 return p;
763}
764
765
766/*
767 * Reallocate memory, reporting a fatal error with bail on failure.
768 */
769void *
770brealloc(void *p, size_t size)
771{
772 p = realloc(p, size);
773 if (p == NULL)
774 sysbail("failed to realloc %lu bytes", (unsigned long) size);
775 return p;
776}
777
778
779/*
780 * The same as brealloc, but determine the size by multiplying an element
781 * count by a size, similar to calloc. The multiplication is checked for
782 * integer overflow.
783 *
784 * We should technically use SIZE_MAX here for the overflow check, but
785 * SIZE_MAX is C99 and we're only assuming C89 + SUSv3, which does not
786 * guarantee that it exists. They do guarantee that UINT_MAX exists, and we
787 * can assume that UINT_MAX <= SIZE_MAX.
788 *
789 * (In theory, C89 and C99 permit size_t to be smaller than unsigned int, but
790 * I disbelieve in the existence of such systems and they will have to cope
791 * without overflow checks.)
792 */
793void *
794breallocarray(void *p, size_t n, size_t size)
795{
796 if (n > 0 && UINT_MAX / n <= size)
797 bail("reallocarray too large");
798 p = realloc(p, n * size);
799 if (p == NULL)
800 sysbail("failed to realloc %lu bytes", (unsigned long) (n * size));
801 return p;
802}
803
804
805/*
806 * Copy a string, reporting a fatal error with bail on failure.
807 */
808char *
809bstrdup(const char *s)
810{
811 char *p;
812 size_t len;
813
814 len = strlen(s) + 1;
815 p = malloc(len);
816 if (p == NULL)
817 sysbail("failed to strdup %lu bytes", (unsigned long) len);
818 memcpy(p, s, len);
819 return p;
820}
821
822
823/*
824 * Copy up to n characters of a string, reporting a fatal error with bail on
825 * failure. Don't use the system strndup function, since it may not exist and
826 * the TAP library doesn't assume any portability support.
827 */
828char *
829bstrndup(const char *s, size_t n)
830{
831 const char *p;
832 char *copy;
833 size_t length;
834
835 /* Don't assume that the source string is nul-terminated. */
836 for (p = s; (size_t) (p - s) < n && *p != '\0'; p++)
837 ;
838 length = (size_t) (p - s);
839 copy = malloc(length + 1);
840 if (p == NULL)
841 sysbail("failed to strndup %lu bytes", (unsigned long) length);
842 memcpy(copy, s, length);
843 copy[length] = '\0';
844 return copy;
845}
846
847
848/*
849 * Locate a test file. Given the partial path to a file, look under
850 * C_TAP_BUILD and then C_TAP_SOURCE for the file and return the full path to
851 * the file. Returns NULL if the file doesn't exist. A non-NULL return
852 * should be freed with test_file_path_free().
853 */
854char *
855test_file_path(const char *file)
856{
857 char *base;
858 char *path = NULL;
859 const char *envs[] = { "C_TAP_BUILD", "C_TAP_SOURCE", NULL };
860 int i;
861
862 for (i = 0; envs[i] != NULL; i++) {
863 base = getenv(envs[i]);
864 if (base == NULL)
865 continue;
866 path = concat(base, "/", file, (const char *) 0);
867 if (access(path, R_OK) == 0)
868 break;
869 free(path);
870 path = NULL;
871 }
872 return path;
873}
874
875
876/*
877 * Free a path returned from test_file_path(). This function exists primarily
878 * for Windows, where memory must be freed from the same library domain that
879 * it was allocated from.
880 */
881void
882test_file_path_free(char *path)
883{
884 free(path);
885}
886
887
888/*
889 * Create a temporary directory, tmp, under C_TAP_BUILD if set and the current
890 * directory if it does not. Returns the path to the temporary directory in
891 * newly allocated memory, and calls bail on any failure. The return value
892 * should be freed with test_tmpdir_free.
893 *
894 * This function uses sprintf because it attempts to be independent of all
895 * other portability layers. The use immediately after a memory allocation
896 * should be safe without using snprintf or strlcpy/strlcat.
897 */
898char *
899test_tmpdir(void)
900{
901 const char *build;
902 char *path = NULL;
903
904 build = getenv("C_TAP_BUILD");
905 if (build == NULL)
906 build = ".";
907 path = concat(build, "/tmp", (const char *) 0);
908 if (access(path, X_OK) < 0)
909 if (mkdir(path, 0777) < 0)
910 sysbail("error creating temporary directory %s", path);
911 return path;
912}
913
914
915/*
916 * Free a path returned from test_tmpdir() and attempt to remove the
917 * directory. If we can't delete the directory, don't worry; something else
918 * that hasn't yet cleaned up may still be using it.
919 */
920void
921test_tmpdir_free(char *path)
922{
923 if (path != NULL)
924 rmdir(path);
925 free(path);
926}
927
928
929/*
930 * Register a cleanup function that is called when testing ends. All such
931 * registered functions will be run by finish.
932 */
933void
934test_cleanup_register(test_cleanup_func func)
935{
936 struct cleanup_func *cleanup, **last;
937
938 cleanup = bmalloc(sizeof(struct cleanup_func));
939 cleanup->func = func;
940 cleanup->next = NULL;
941 last = &cleanup_funcs;
942 while (*last != NULL)
943 last = &(*last)->next;
944 *last = cleanup;
945}