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 | |
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')
-rw-r--r-- | tests/tap/basic.c | 214 | ||||
-rw-r--r-- | tests/tap/basic.h | 43 | ||||
-rw-r--r-- | tests/tap/kerberos.c | 9 | ||||
-rw-r--r-- | tests/tap/kerberos.h | 26 | ||||
-rw-r--r-- | tests/tap/macros.h | 32 | ||||
-rw-r--r-- | tests/tap/perl/Test/RRA.pm | 81 | ||||
-rw-r--r-- | tests/tap/perl/Test/RRA/Automake.pm | 19 | ||||
-rw-r--r-- | tests/tap/perl/Test/RRA/Config.pm | 14 | ||||
-rw-r--r-- | tests/tap/perl/Test/RRA/ModuleVersion.pm | 20 | ||||
-rw-r--r-- | tests/tap/process.c | 18 | ||||
-rw-r--r-- | tests/tap/process.h | 3 | ||||
-rw-r--r-- | tests/tap/string.h | 2 |
12 files changed, 278 insertions, 203 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); +} diff --git a/tests/tap/basic.h b/tests/tap/basic.h index 3f46e4f..45f15f2 100644 --- a/tests/tap/basic.h +++ b/tests/tap/basic.h @@ -5,7 +5,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-2012, 2014 * The Board of Trustees of the Leland Stanford Junior University * @@ -33,9 +33,9 @@ #ifndef TAP_BASIC_H #define TAP_BASIC_H 1 +#include <stdarg.h> /* va_list */ +#include <stddef.h> /* size_t */ #include <tests/tap/macros.h> -#include <stdarg.h> /* va_list */ -#include <stddef.h> /* size_t */ /* * Used for iterating through arrays. ARRAY_SIZE returns the number of @@ -43,8 +43,8 @@ * ARRAY_END returns a pointer to the element past the end (ISO C99 makes it * legal to refer to such a pointer as long as it's never dereferenced). */ -#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) -#define ARRAY_END(array) (&(array)[ARRAY_SIZE(array)]) +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#define ARRAY_END(array) (&(array)[ARRAY_SIZE(array)]) BEGIN_DECLS @@ -77,8 +77,7 @@ int ok(int success, const char *format, ...) __attribute__((__format__(printf, 2, 3))); int okv(int success, const char *format, va_list args) __attribute__((__format__(printf, 2, 0))); -void skip(const char *reason, ...) - __attribute__((__format__(printf, 1, 2))); +void skip(const char *reason, ...) __attribute__((__format__(printf, 1, 2))); /* * Report the same status on, or skip, the next count tests. ok_block() @@ -125,10 +124,8 @@ int sysdiag(const char *format, ...) * diag(). Nul characters are not supported in these files and will result in * truncated output. */ -void diag_file_add(const char *file) - __attribute__((__nonnull__)); -void diag_file_remove(const char *file) - __attribute__((__nonnull__)); +void diag_file_add(const char *file) __attribute__((__nonnull__)); +void diag_file_remove(const char *file) __attribute__((__nonnull__)); /* Allocate memory, reporting a fatal error with bail on failure. */ void *bcalloc(size_t, size_t) @@ -145,6 +142,14 @@ char *bstrndup(const char *, size_t) __attribute__((__malloc__, __nonnull__, __warn_unused_result__)); /* + * Macros that cast the return value from b* memory functions, making them + * usable in C++ code and providing some additional type safety. + */ +#define bcalloc_type(n, type) ((type *) bcalloc((n), sizeof(type))) +#define breallocarray_type(p, n, type) \ + ((type *) breallocarray((p), (n), sizeof(type))) + +/* * Find a test file under C_TAP_BUILD or C_TAP_SOURCE, returning the full * path. The returned path should be freed with test_file_path_free(). */ @@ -156,8 +161,7 @@ void test_file_path_free(char *path); * Create a temporary directory relative to C_TAP_BUILD and return the path. * The returned path should be freed with test_tmpdir_free(). */ -char *test_tmpdir(void) - __attribute__((__malloc__, __warn_unused_result__)); +char *test_tmpdir(void) __attribute__((__malloc__, __warn_unused_result__)); void test_tmpdir_free(char *path); /* @@ -168,10 +172,19 @@ void test_tmpdir_free(char *path); * The function must return void and will be passed two arguments: an int that * will be true if the test completed successfully and false otherwise, and an * int that will be true if the cleanup function is run in the primary process - * (the one that called plan or plan_lazy) and false otherwise. + * (the one that called plan or plan_lazy) and false otherwise. If + * test_cleanup_register_with_data is used instead, a generic pointer can be + * provided and will be passed to the cleanup function as a third argument. + * + * test_cleanup_register_with_data is the better API and should have been the + * only API. test_cleanup_register was an API error preserved for backward + * cmpatibility. */ typedef void (*test_cleanup_func)(int, int); -void test_cleanup_register(test_cleanup_func) +typedef void (*test_cleanup_func_with_data)(int, int, void *); + +void test_cleanup_register(test_cleanup_func) __attribute__((__nonnull__)); +void test_cleanup_register_with_data(test_cleanup_func_with_data, void *) __attribute__((__nonnull__)); END_DECLS diff --git a/tests/tap/kerberos.c b/tests/tap/kerberos.c index 89a36a3..765d802 100644 --- a/tests/tap/kerberos.c +++ b/tests/tap/kerberos.c @@ -42,7 +42,7 @@ #include <config.h> #ifdef HAVE_KRB5 -# include <portable/krb5.h> +# include <portable/krb5.h> #endif #include <portable/system.h> @@ -59,7 +59,7 @@ * to handle the possible patterns for kinit commands as an array. */ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) || defined(__clang__) -# pragma GCC diagnostic ignored "-Wformat-nonliteral" +# pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif @@ -158,12 +158,11 @@ kerberos_kinit(void) static void kerberos_kinit(void) { - static const char * const format[] = { + static const char *const format[] = { "kinit --no-afslog -k -t %s %s >/dev/null 2>&1 </dev/null", "kinit -k -t %s %s >/dev/null 2>&1 </dev/null", "kinit -t %s %s >/dev/null 2>&1 </dev/null", - "kinit -k -K %s %s >/dev/null 2>&1 </dev/null" - }; + "kinit -k -K %s %s >/dev/null 2>&1 </dev/null"}; FILE *file; char *path; char principal[BUFSIZ], *command; diff --git a/tests/tap/kerberos.h b/tests/tap/kerberos.h index c256822..0664905 100644 --- a/tests/tap/kerberos.h +++ b/tests/tap/kerberos.h @@ -5,7 +5,7 @@ * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>. * * Written by Russ Allbery <eagle@eyrie.org> - * Copyright 2017 Russ Allbery <eagle@eyrie.org> + * Copyright 2017, 2020 Russ Allbery <eagle@eyrie.org> * Copyright 2006-2007, 2009, 2011-2014 * The Board of Trustees of the Leland Stanford Junior University * @@ -37,20 +37,20 @@ #include <tests/tap/macros.h> #ifdef HAVE_KRB5 -# include <portable/krb5.h> +# include <portable/krb5.h> #endif /* Holds the information parsed from the Kerberos test configuration. */ struct kerberos_config { - char *keytab; /* Path to the keytab. */ - char *principal; /* Principal whose keys are in the keytab. */ - char *cache; /* Path to the Kerberos ticket cache. */ - char *userprinc; /* The fully-qualified principal. */ - char *username; /* The local (non-realm) part of principal. */ - char *realm; /* The realm part of the principal. */ - char *password; /* The password. */ - char *pkinit_principal; /* Principal for PKINIT authentication. */ - char *pkinit_cert; /* Path to certificates for PKINIT. */ + char *keytab; /* Path to the keytab. */ + char *principal; /* Principal whose keys are in the keytab. */ + char *cache; /* Path to the Kerberos ticket cache. */ + char *userprinc; /* The fully-qualified principal. */ + char *username; /* The local (non-realm) part of principal. */ + char *realm; /* The realm part of the principal. */ + char *password; /* The password. */ + char *pkinit_principal; /* Principal for PKINIT authentication. */ + char *pkinit_cert; /* Path to certificates for PKINIT. */ }; /* @@ -59,11 +59,13 @@ struct kerberos_config { * tests require both keytab and password, but PKINIT is not required. */ enum kerberos_needs { + /* clang-format off */ TAP_KRB_NEEDS_NONE = 0x00, TAP_KRB_NEEDS_KEYTAB = 0x01, TAP_KRB_NEEDS_PASSWORD = 0x02, TAP_KRB_NEEDS_BOTH = 0x01 | 0x02, TAP_KRB_NEEDS_PKINIT = 0x04 + /* clang-format on */ }; BEGIN_DECLS @@ -106,7 +108,7 @@ void kerberos_cleanup(void); void kerberos_generate_conf(const char *realm); void kerberos_cleanup_conf(void); -/* Thes interfaces are only available with native Kerberos support. */ +/* These interfaces are only available with native Kerberos support. */ #ifdef HAVE_KRB5 /* Bail out with an error, appending the Kerberos error message. */ diff --git a/tests/tap/macros.h b/tests/tap/macros.h index cc6d104..c2c8b5c 100644 --- a/tests/tap/macros.h +++ b/tests/tap/macros.h @@ -42,9 +42,9 @@ * the other attributes to work with GCC versions between 2.7 and 2.96. */ #ifndef __attribute__ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) -# define __attribute__(spec) /* empty */ -# endif +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) +# define __attribute__(spec) /* empty */ +# endif #endif /* @@ -55,18 +55,18 @@ * variadic macro support. */ #if !defined(__attribute__) && !defined(__alloc_size__) -# if defined(__GNUC__) && !defined(__clang__) -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) -# define __alloc_size__(spec, args...) /* empty */ -# endif -# endif +# if defined(__GNUC__) && !defined(__clang__) +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) +# define __alloc_size__(spec, args...) /* empty */ +# endif +# endif #endif /* Suppress __warn_unused_result__ if gcc is too old. */ #if !defined(__attribute__) && !defined(__warn_unused_result__) -# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) -# define __warn_unused_result__ /* empty */ -# endif +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +# define __warn_unused_result__ /* empty */ +# endif #endif /* @@ -76,7 +76,7 @@ * compilation context, but there's no push and pop available. */ #if !defined(__attribute__) && (defined(__llvm__) || defined(__clang__)) -# pragma GCC diagnostic ignored "-Wattributes" +# pragma GCC diagnostic ignored "-Wattributes" #endif /* Used for unused parameters to silence gcc warnings. */ @@ -89,11 +89,11 @@ #undef BEGIN_DECLS #undef END_DECLS #ifdef __cplusplus -# define BEGIN_DECLS extern "C" { -# define END_DECLS } +# define BEGIN_DECLS extern "C" { +# define END_DECLS } #else -# define BEGIN_DECLS /* empty */ -# define END_DECLS /* empty */ +# define BEGIN_DECLS /* empty */ +# define END_DECLS /* empty */ #endif #endif /* TAP_MACROS_H */ diff --git a/tests/tap/perl/Test/RRA.pm b/tests/tap/perl/Test/RRA.pm index 3b2f584..cd106d0 100644 --- a/tests/tap/perl/Test/RRA.pm +++ b/tests/tap/perl/Test/RRA.pm @@ -10,25 +10,41 @@ package Test::RRA; -use 5.006; +use 5.008; +use base qw(Exporter); use strict; use warnings; -use Exporter; +use Carp qw(croak); use File::Temp; -use Test::More; -# For Perl 5.006 compatibility. -## no critic (ClassHierarchies::ProhibitExplicitISA) +# Abort if Test::More was loaded before Test::RRA to be sure that we get the +# benefits of the Test::More probing below. +if ($INC{'Test/More.pm'}) { + croak('Test::More loaded before Test::RRA'); +} + +# Red Hat's base perl package doesn't include Test::More (one has to install +# the perl-core package in addition). Try to detect this and skip any Perl +# tests if Test::More is not present. This relies on Test::RRA being included +# before Test::More. +eval { + require Test::More; + Test::More->import(); +}; +if ($@) { + print "1..0 # SKIP Test::More required for test\n" + or croak('Cannot write to stdout'); + exit 0; +} # Declare variables that should be set in BEGIN for robustness. -our (@EXPORT_OK, @ISA, $VERSION); +our (@EXPORT_OK, $VERSION); # Set $VERSION and everything export-related in a BEGIN block for robustness # against circular module loading (not that we load any modules, but # consistency is good). BEGIN { - @ISA = qw(Exporter); @EXPORT_OK = qw( is_file_contents skip_unless_author skip_unless_automated use_prereq ); @@ -36,7 +52,7 @@ BEGIN { # This version should match the corresponding rra-c-util release, but with # two digits for the minor version, including a leading zero if necessary, # so that it will sort properly. - $VERSION = '7.02'; + $VERSION = '8.02'; } # Compare a string to the contents of a file, similar to the standard is() @@ -61,22 +77,27 @@ sub is_file_contents { return; } - # Otherwise, we show a diff, but only if we have IPC::System::Simple. - eval { require IPC::System::Simple }; + # Otherwise, we show a diff, but only if we have IPC::System::Simple and + # diff succeeds. Otherwise, we fall back on showing the full expected and + # seen output. + eval { + require IPC::System::Simple; + + my $tmp = File::Temp->new(); + my $tmpname = $tmp->filename; + print {$tmp} $got or BAIL_OUT("Cannot write to $tmpname: $!\n"); + my @command = ('diff', '-u', $expected, $tmpname); + my $diff = IPC::System::Simple::capturex([0 .. 1], @command); + diag($diff); + }; if ($@) { - ok(0, $message); - return; + diag('Expected:'); + diag($expected); + diag('Seen:'); + diag($data); } - # They're not equal. Write out what we got so that we can run diff. - my $tmp = File::Temp->new(); - my $tmpname = $tmp->filename; - print {$tmp} $got or BAIL_OUT("Cannot write to $tmpname: $!\n"); - my @command = ('diff', '-u', $expected, $tmpname); - my $diff = IPC::System::Simple::capturex([0 .. 1], @command); - diag($diff); - - # Remove the temporary file and report failure. + # Report failure. ok(0, $message); return; } @@ -91,7 +112,7 @@ sub is_file_contents { sub skip_unless_author { my ($description) = @_; if (!$ENV{AUTHOR_TESTING}) { - plan skip_all => "$description only run for author"; + plan(skip_all => "$description only run for author"); } return; } @@ -110,7 +131,7 @@ sub skip_unless_automated { for my $env (qw(AUTOMATED_TESTING RELEASE_TESTING AUTHOR_TESTING)) { return if $ENV{$env}; } - plan skip_all => "$description normally skipped"; + plan(skip_all => "$description normally skipped"); return; } @@ -152,14 +173,14 @@ sub use_prereq { use $module $version \@imports; 1; }; - $error = $@; + $error = $@; $sigdie = $SIG{__DIE__} || undef; } # If the use failed for any reason, skip the test. if (!$result || $error) { my $name = length($version) > 0 ? "$module $version" : $module; - plan skip_all => "$name required for test"; + plan(skip_all => "$name required for test"); } # If the module set $SIG{__DIE__}, we cleared that via local. Restore it. @@ -202,6 +223,14 @@ This module collects utility functions that are useful for Perl test scripts. It assumes Russ Allbery's Perl module layout and test conventions and will only be useful for other people if they use the same conventions. +This module B<must> be loaded before Test::More or it will abort during +import. It will skip the test (by printing a skip message to standard output +and exiting with status 0, equivalent to C<plan skip_all>) during import if +Test::More is not available. This allows tests written in Perl using this +module to be skipped if run on a system with Perl but not Test::More, such as +Red Hat systems with the C<perl> package but not the C<perl-core> package +installed. + =head1 FUNCTIONS None of these functions are imported by default. The ones used by a script @@ -246,7 +275,7 @@ Russ Allbery <eagle@eyrie.org> =head1 COPYRIGHT AND LICENSE -Copyright 2016 Russ Allbery <eagle@eyrie.org> +Copyright 2016, 2018-2019 Russ Allbery <eagle@eyrie.org> Copyright 2013-2014 The Board of Trustees of the Leland Stanford Junior University diff --git a/tests/tap/perl/Test/RRA/Automake.pm b/tests/tap/perl/Test/RRA/Automake.pm index 69fff6a..16c9b01 100644 --- a/tests/tap/perl/Test/RRA/Automake.pm +++ b/tests/tap/perl/Test/RRA/Automake.pm @@ -15,13 +15,11 @@ package Test::RRA::Automake; -use 5.006; +use 5.008; +use base qw(Exporter); use strict; use warnings; -# For Perl 5.006 compatibility. -## no critic (ClassHierarchies::ProhibitExplicitISA) - use Exporter; use File::Find qw(find); use File::Spec; @@ -54,13 +52,12 @@ use lib $PERL_BLIB_ARCH; use lib $PERL_BLIB_LIB; # Declare variables that should be set in BEGIN for robustness. -our (@EXPORT_OK, @ISA, $VERSION); +our (@EXPORT_OK, $VERSION); # Set $VERSION and everything export-related in a BEGIN block for robustness # against circular module loading (not that we load any modules, but # consistency is good). BEGIN { - @ISA = qw(Exporter); @EXPORT_OK = qw( all_files automake_setup perl_dirs test_file_path test_tmpdir ); @@ -68,13 +65,13 @@ BEGIN { # This version should match the corresponding rra-c-util release, but with # two digits for the minor version, including a leading zero if necessary, # so that it will sort properly. - $VERSION = '7.02'; + $VERSION = '8.02'; } # Directories to skip globally when looking for all files, or for directories # that could contain Perl files. my @GLOBAL_SKIP = qw( - .git _build autom4te.cache build-aux perl/_build perl/blib + .git .pc _build autom4te.cache build-aux perl/_build perl/blib ); # Additional paths to skip when building a list of all files in the @@ -189,7 +186,7 @@ sub automake_setup { @builddirs = File::Spec->splitdir($builddirs); pop(@builddirs); my $libdir = File::Spec->catdir(@builddirs, $LIBRARY_PATH); - my $path = File::Spec->catpath($buildvol, $libdir, q{}); + my $path = File::Spec->catpath($buildvol, $libdir, q{}); if (-d "$path/.libs") { $path .= '/.libs'; } @@ -229,7 +226,7 @@ sub perl_dirs { } # Convert the skip lists into hashes for convenience. - my %skip = map { $_ => 1 } @skip, 'tests'; + my %skip = map { $_ => 1 } @skip, 'tests'; my %skip_tests = map { $_ => 1 } @skip_tests; # Build the list of top-level directories to test. @@ -451,7 +448,7 @@ Russ Allbery <eagle@eyrie.org> =head1 COPYRIGHT AND LICENSE -Copyright 2014-2015, 2018 Russ Allbery <eagle@eyrie.org> +Copyright 2014-2015, 2018-2020 Russ Allbery <eagle@eyrie.org> Copyright 2013 The Board of Trustees of the Leland Stanford Junior University diff --git a/tests/tap/perl/Test/RRA/Config.pm b/tests/tap/perl/Test/RRA/Config.pm index 40641f1..7064140 100644 --- a/tests/tap/perl/Test/RRA/Config.pm +++ b/tests/tap/perl/Test/RRA/Config.pm @@ -9,24 +9,20 @@ package Test::RRA::Config; -use 5.006; +use 5.008; +use base qw(Exporter); use strict; use warnings; -# For Perl 5.006 compatibility. -## no critic (ClassHierarchies::ProhibitExplicitISA) - -use Exporter; use Test::More; # Declare variables that should be set in BEGIN for robustness. -our (@EXPORT_OK, @ISA, $VERSION); +our (@EXPORT_OK, $VERSION); # Set $VERSION and everything export-related in a BEGIN block for robustness # against circular module loading (not that we load any modules, but # consistency is good). BEGIN { - @ISA = qw(Exporter); @EXPORT_OK = qw( $COVERAGE_LEVEL @COVERAGE_SKIP_TESTS @CRITIC_IGNORE $LIBRARY_PATH $MINIMUM_VERSION %MINIMUM_VERSION @MODULE_VERSION_IGNORE @@ -36,7 +32,7 @@ BEGIN { # This version should match the corresponding rra-c-util release, but with # two digits for the minor version, including a leading zero if necessary, # so that it will sort properly. - $VERSION = '7.02'; + $VERSION = '8.02'; } # If C_TAP_BUILD or C_TAP_SOURCE are set in the environment, look for @@ -187,7 +183,7 @@ Russ Allbery <eagle@eyrie.org> =head1 COPYRIGHT AND LICENSE -Copyright 2015-2016 Russ Allbery <eagle@eyrie.org> +Copyright 2015-2016, 2019 Russ Allbery <eagle@eyrie.org> Copyright 2013-2014 The Board of Trustees of the Leland Stanford Junior University diff --git a/tests/tap/perl/Test/RRA/ModuleVersion.pm b/tests/tap/perl/Test/RRA/ModuleVersion.pm index 8b6dba2..7774351 100644 --- a/tests/tap/perl/Test/RRA/ModuleVersion.pm +++ b/tests/tap/perl/Test/RRA/ModuleVersion.pm @@ -8,32 +8,28 @@ package Test::RRA::ModuleVersion; -use 5.006; +use 5.008; +use base qw(Exporter); use strict; use warnings; -use Exporter; use File::Find qw(find); use Test::More; use Test::RRA::Config qw(@MODULE_VERSION_IGNORE); -# For Perl 5.006 compatibility. -## no critic (ClassHierarchies::ProhibitExplicitISA) - # Declare variables that should be set in BEGIN for robustness. -our (@EXPORT_OK, @ISA, $VERSION); +our (@EXPORT_OK, $VERSION); # Set $VERSION and everything export-related in a BEGIN block for robustness # against circular module loading (not that we load any modules, but # consistency is good). BEGIN { - @ISA = qw(Exporter); @EXPORT_OK = qw(test_module_versions update_module_versions); # This version should match the corresponding rra-c-util release, but with # two digits for the minor version, including a leading zero if necessary, # so that it will sort properly. - $VERSION = '7.02'; + $VERSION = '8.02'; } # A regular expression matching the version string for a module using the @@ -139,7 +135,7 @@ sub _update_module_version { } # Scan for the version and replace it. - open(my $in, q{<}, $file) or die "$0: cannot open $file: $!\n"; + open(my $in, q{<}, $file) or die "$0: cannot open $file: $!\n"; open(my $out, q{>}, "$file.new") or die "$0: cannot create $file.new: $!\n"; SCAN: @@ -155,8 +151,8 @@ sub _update_module_version { # Copy the rest of the input file to the output file. print {$out} <$in> or die "$0: cannot write to $file.new: $!\n"; - close($out) or die "$0: cannot flush $file.new: $!\n"; - close($in) or die "$0: error reading from $file: $!\n"; + close($out) or die "$0: cannot flush $file.new: $!\n"; + close($in) or die "$0: error reading from $file: $!\n"; # All done. Rename the new file over top of the old file. rename("$file.new", $file) @@ -269,7 +265,7 @@ Russ Allbery <eagle@eyrie.org> =head1 COPYRIGHT AND LICENSE -Copyright 2016, 2018 Russ Allbery <eagle@eyrie.org> +Copyright 2016, 2018-2019 Russ Allbery <eagle@eyrie.org> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/tests/tap/process.c b/tests/tap/process.c index d9e94d8..2f797f8 100644 --- a/tests/tap/process.c +++ b/tests/tap/process.c @@ -46,11 +46,11 @@ #include <fcntl.h> #include <signal.h> #ifdef HAVE_SYS_SELECT_H -# include <sys/select.h> +# include <sys/select.h> #endif #include <sys/stat.h> #ifdef HAVE_SYS_TIME_H -# include <sys/time.h> +# include <sys/time.h> #endif #include <sys/wait.h> #include <time.h> @@ -61,7 +61,7 @@ /* May be defined by the build system. */ #ifndef PATH_FAKEROOT -# define PATH_FAKEROOT "" +# define PATH_FAKEROOT "" #endif /* How long to wait for the process to start in seconds. */ @@ -72,12 +72,12 @@ * everything required to stop the process and clean up after it. */ struct process { - pid_t pid; /* PID of child process */ - char *pidfile; /* PID file to delete on process stop */ - char *tmpdir; /* Temporary directory for log file */ - char *logfile; /* Log file of process output */ - bool is_child; /* Whether we can waitpid for process */ - struct process *next; /* Next process in global list */ + pid_t pid; /* PID of child process */ + char *pidfile; /* PID file to delete on process stop */ + char *tmpdir; /* Temporary directory for log file */ + char *logfile; /* Log file of process output */ + bool is_child; /* Whether we can waitpid for process */ + struct process *next; /* Next process in global list */ }; /* diff --git a/tests/tap/process.h b/tests/tap/process.h index da21ad3..4210c20 100644 --- a/tests/tap/process.h +++ b/tests/tap/process.h @@ -62,8 +62,7 @@ void is_function_output(test_function_type, void *data, int status, * successfully, call bail, with the error message being the output from the * program. */ -void run_setup(const char *const argv[]) - __attribute__((__nonnull__)); +void run_setup(const char *const argv[]) __attribute__((__nonnull__)); /* * process_start starts a process in the background, returning an opaque data diff --git a/tests/tap/string.h b/tests/tap/string.h index a520210..651c38a 100644 --- a/tests/tap/string.h +++ b/tests/tap/string.h @@ -36,7 +36,7 @@ #include <config.h> #include <tests/tap/macros.h> -#include <stdarg.h> /* va_list */ +#include <stdarg.h> /* va_list */ BEGIN_DECLS |