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