diff options
author | Russ Allbery <eagle@eyrie.org> | 2020-05-17 17:05:30 -0700 |
---|---|---|
committer | Russ Allbery <eagle@eyrie.org> | 2020-05-17 17:05:30 -0700 |
commit | c138111a3c27863308b6552a5527a9e821a3dc11 (patch) | |
tree | fe3c16462bf0213708f20d251a63e5b9bbf2d23f /tests/tap/basic.c | |
parent | ccfbd34d597318215b979338c4cb5d7e4a3f0d6f (diff) |
Update to rra-c-util 8.2 and C TAP Harness 4.7
Update to rra-c-util 8.2:
* Implement explicit_bzero with memset if it is not available.
* Reformat all C source using clang-format 10.
* Work around Test::Strict not skipping .git directories.
* Fix warnings with perltidy 20190601 and Perl::Critic 1.134.
* Fix warnings with Clang 10, GCC 10, and the Clang static analyzer.
Update to C TAP Harness 4.7:
* Fix warnings with GCC 10.
* Reformat all C source using clang-format 10.
* Fixed malloc error checking in bstrndup.
Diffstat (limited to 'tests/tap/basic.c')
-rw-r--r-- | tests/tap/basic.c | 214 |
1 files changed, 129 insertions, 85 deletions
diff --git a/tests/tap/basic.c b/tests/tap/basic.c index 8624839..b5f42d0 100644 --- a/tests/tap/basic.c +++ b/tests/tap/basic.c @@ -13,7 +13,7 @@ * documentation is at <https://www.eyrie.org/~eagle/software/c-tap-harness/>. * * Written by Russ Allbery <eagle@eyrie.org> - * Copyright 2009-2018 Russ Allbery <eagle@eyrie.org> + * Copyright 2009-2019 Russ Allbery <eagle@eyrie.org> * Copyright 2001-2002, 2004-2008, 2011-2014 * The Board of Trustees of the Leland Stanford Junior University * @@ -45,9 +45,9 @@ #include <stdlib.h> #include <string.h> #ifdef _WIN32 -# include <direct.h> +# include <direct.h> #else -# include <sys/stat.h> +# include <sys/stat.h> #endif #include <sys/types.h> #include <unistd.h> @@ -56,8 +56,8 @@ /* Windows provides mkdir and rmdir under different names. */ #ifdef _WIN32 -# define mkdir(p, m) _mkdir(p) -# define rmdir(p) _rmdir(p) +# define mkdir(p, m) _mkdir(p) +# define rmdir(p) _rmdir(p) #endif /* @@ -72,7 +72,7 @@ unsigned long testnum = 1; * We can get the highest test count from testnum. */ static unsigned long _planned = 0; -static unsigned long _failed = 0; +static unsigned long _failed = 0; /* * Store the PID of the process that called plan() and only summarize @@ -101,6 +101,8 @@ static int _aborted = 0; */ struct cleanup_func { test_cleanup_func func; + test_cleanup_func_with_data func_with_data; + void *data; struct cleanup_func *next; }; static struct cleanup_func *cleanup_funcs = NULL; @@ -126,15 +128,15 @@ static struct diag_file *diag_files = NULL; * print_desc, which has to be done in a macro. Assumes that format is the * argument immediately before the variadic arguments. */ -#define PRINT_DESC(prefix, format) \ - do { \ - if (format != NULL) { \ - va_list args; \ - printf("%s", prefix); \ - va_start(args, format); \ - vprintf(format, args); \ - va_end(args); \ - } \ +#define PRINT_DESC(prefix, format) \ + do { \ + if (format != NULL) { \ + va_list args; \ + printf("%s", prefix); \ + va_start(args, format); \ + vprintf(format, args); \ + va_end(args); \ + } \ } while (0) @@ -171,7 +173,7 @@ concat(const char *first, ...) length++; /* Create the string. */ - result = bmalloc(length); + result = bcalloc_type(length, char); va_start(args, first); offset = 0; for (string = first; string != NULL; string = va_arg(args, const char *)) { @@ -185,6 +187,68 @@ concat(const char *first, ...) /* + * Helper function for check_diag_files to handle a single line in a diag + * file. + * + * The general scheme here used is as follows: read one line of output. If we + * get NULL, check for an error. If there was one, bail out of the test + * program; otherwise, return, and the enclosing loop will check for EOF. + * + * If we get some data, see if it ends in a newline. If it doesn't end in a + * newline, we have one of two cases: our buffer isn't large enough, in which + * case we resize it and try again, or we have incomplete data in the file, in + * which case we rewind the file and will try again next time. + * + * Returns a boolean indicating whether the last line was incomplete. + */ +static int +handle_diag_file_line(struct diag_file *file, fpos_t where) +{ + int size; + size_t length; + + /* Read the next line from the file. */ + size = file->bufsize > INT_MAX ? INT_MAX : (int) file->bufsize; + if (fgets(file->buffer, size, file->file) == NULL) { + if (ferror(file->file)) + sysbail("cannot read from %s", file->name); + return 0; + } + + /* + * See if the line ends in a newline. If not, see which error case we + * have. + */ + length = strlen(file->buffer); + if (file->buffer[length - 1] != '\n') { + int incomplete = 0; + + /* Check whether we ran out of buffer space and resize if so. */ + if (length < file->bufsize - 1) + incomplete = 1; + else { + file->bufsize += BUFSIZ; + file->buffer = + breallocarray_type(file->buffer, file->bufsize, char); + } + + /* + * On either incomplete lines or too small of a buffer, rewind + * and read the file again (on the next pass, if incomplete). + * It's simpler than trying to double-buffer the file. + */ + if (fsetpos(file->file, &where) < 0) + sysbail("cannot set position in %s", file->name); + return incomplete; + } + + /* We saw a complete line. Print it out. */ + printf("# %s", file->buffer); + return 0; +} + + +/* * Check all registered diag_files for any output. We only print out the * output if we see a complete line; otherwise, we wait for the next newline. */ @@ -193,20 +257,10 @@ check_diag_files(void) { struct diag_file *file; fpos_t where; - size_t length; - int size, incomplete; + int incomplete; /* - * Walk through each file and read each line of output available. The - * general scheme here used is as follows: try to read a line of output at - * a time. If we get NULL, check for EOF; on EOF, advance to the next - * file. - * - * If we get some data, see if it ends in a newline. If it doesn't end in - * a newline, we have one of two cases: our buffer isn't large enough, in - * which case we resize it and try again, or we have incomplete data in - * the file, in which case we rewind the file and will try again next - * time. + * Walk through each file and read each line of output available. */ for (file = diag_files; file != NULL; file = file->next) { clearerr(file->file); @@ -218,41 +272,7 @@ check_diag_files(void) /* Continue until we get EOF or an incomplete line of data. */ incomplete = 0; while (!feof(file->file) && !incomplete) { - size = file->bufsize > INT_MAX ? INT_MAX : (int) file->bufsize; - if (fgets(file->buffer, size, file->file) == NULL) { - if (ferror(file->file)) - sysbail("cannot read from %s", file->name); - continue; - } - - /* - * See if the line ends in a newline. If not, see which error - * case we have. Use UINT_MAX as a substitute for SIZE_MAX (see - * the comment for breallocarray). - */ - length = strlen(file->buffer); - if (file->buffer[length - 1] != '\n') { - if (length < file->bufsize - 1) - incomplete = 1; - else { - if (file->bufsize >= UINT_MAX - BUFSIZ) - sysbail("line too long in %s", file->name); - file->bufsize += BUFSIZ; - file->buffer = brealloc(file->buffer, file->bufsize); - } - - /* - * On either incomplete lines or too small of a buffer, rewind - * and read the file again (on the next pass, if incomplete). - * It's simpler than trying to double-buffer the file. - */ - if (fsetpos(file->file, &where) < 0) - sysbail("cannot set position in %s", file->name); - continue; - } - - /* We saw a complete line. Print it out. */ - printf("# %s", file->buffer); + incomplete = handle_diag_file_line(file, where); } } } @@ -305,7 +325,13 @@ finish(void) */ primary = (_process == 0 || getpid() == _process); while (cleanup_funcs != NULL) { - cleanup_funcs->func(success, primary); + if (cleanup_funcs->func_with_data) { + void *data = cleanup_funcs->data; + + cleanup_funcs->func_with_data(success, primary, data); + } else { + cleanup_funcs->func(success, primary); + } current = cleanup_funcs; cleanup_funcs = cleanup_funcs->next; free(current); @@ -503,7 +529,7 @@ is_bool(int left, int right, const char *format, ...) if (success) printf("ok %lu", testnum++); else { - diag(" left: %s", !!left ? "true" : "false"); + diag(" left: %s", !!left ? "true" : "false"); diag("right: %s", !!right ? "true" : "false"); printf("not ok %lu", testnum++); _failed++; @@ -563,7 +589,7 @@ is_string(const char *left, const char *right, const char *format, ...) if (success) printf("ok %lu", testnum++); else { - diag(" left: %s", left == NULL ? "(null)" : left); + diag(" left: %s", left == NULL ? "(null)" : left); diag("right: %s", right == NULL ? "(null)" : right); printf("not ok %lu", testnum++); _failed++; @@ -617,8 +643,8 @@ is_blob(const void *left, const void *right, size_t len, const char *format, if (success) printf("ok %lu", testnum++); else { - const unsigned char *left_c = left; - const unsigned char *right_c = right; + const unsigned char *left_c = (const unsigned char *) left; + const unsigned char *right_c = (const unsigned char *) right; for (i = 0; i < len; i++) { if (left_c[i] != right_c[i]) @@ -728,12 +754,12 @@ diag_file_add(const char *name) { struct diag_file *file, *prev; - file = bcalloc(1, sizeof(struct diag_file)); + file = bcalloc_type(1, struct diag_file); file->name = bstrdup(name); file->file = fopen(file->name, "r"); if (file->file == NULL) sysbail("cannot open %s", name); - file->buffer = bmalloc(BUFSIZ); + file->buffer = bcalloc_type(BUFSIZ, char); file->bufsize = BUFSIZ; if (diag_files == NULL) diag_files = file; @@ -781,7 +807,7 @@ bcalloc(size_t n, size_t size) p = calloc(n, size); if (p == NULL) - sysbail("failed to calloc %lu", (unsigned long)(n * size)); + sysbail("failed to calloc %lu", (unsigned long) (n * size)); return p; } @@ -852,7 +878,7 @@ bstrdup(const char *s) size_t len; len = strlen(s) + 1; - p = malloc(len); + p = (char *) malloc(len); if (p == NULL) sysbail("failed to strdup %lu bytes", (unsigned long) len); memcpy(p, s, len); @@ -873,11 +899,11 @@ bstrndup(const char *s, size_t n) size_t length; /* Don't assume that the source string is nul-terminated. */ - for (p = s; (size_t) (p - s) < n && *p != '\0'; p++) + for (p = s; (size_t)(p - s) < n && *p != '\0'; p++) ; - length = (size_t) (p - s); - copy = malloc(length + 1); - if (p == NULL) + length = (size_t)(p - s); + copy = (char *) malloc(length + 1); + if (copy == NULL) sysbail("failed to strndup %lu bytes", (unsigned long) length); memcpy(copy, s, length); copy[length] = '\0'; @@ -896,7 +922,7 @@ test_file_path(const char *file) { char *base; char *path = NULL; - const char *envs[] = { "C_TAP_BUILD", "C_TAP_SOURCE", NULL }; + const char *envs[] = {"C_TAP_BUILD", "C_TAP_SOURCE", NULL}; int i; for (i = 0; envs[i] != NULL; i++) { @@ -965,21 +991,39 @@ test_tmpdir_free(char *path) free(path); } - -/* - * Register a cleanup function that is called when testing ends. All such - * registered functions will be run by finish. - */ -void -test_cleanup_register(test_cleanup_func func) +static void +register_cleanup(test_cleanup_func func, + test_cleanup_func_with_data func_with_data, void *data) { struct cleanup_func *cleanup, **last; - cleanup = bmalloc(sizeof(struct cleanup_func)); + cleanup = bcalloc_type(1, struct cleanup_func); cleanup->func = func; + cleanup->func_with_data = func_with_data; + cleanup->data = data; cleanup->next = NULL; last = &cleanup_funcs; while (*last != NULL) last = &(*last)->next; *last = cleanup; } + +/* + * Register a cleanup function that is called when testing ends. All such + * registered functions will be run by finish. + */ +void +test_cleanup_register(test_cleanup_func func) +{ + register_cleanup(func, NULL, NULL); +} + +/* + * Same as above, but also allows an opaque pointer to be passed to the cleanup + * function. + */ +void +test_cleanup_register_with_data(test_cleanup_func_with_data func, void *data) +{ + register_cleanup(NULL, func, data); +} |