diff options
author | Chris Dickens <christopher.a.dickens@gmail.com> | 2020-09-13 15:30:04 -0700 |
---|---|---|
committer | Chris Dickens <christopher.a.dickens@gmail.com> | 2020-11-07 21:11:33 -0800 |
commit | a016a082a8143409006d954112b5130bc7e9449c (patch) | |
tree | f799ecc5f92352b1d552cea406dbac03547be175 /tests | |
parent | 84e860cfb9cb3fb7a6af8211c8558525e3c6abae (diff) | |
download | libusb-a016a082a8143409006d954112b5130bc7e9449c.tar.gz |
tests: Refactor testlib to simplify and fix Cygwin build
Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/libusb_testlib.h | 55 | ||||
-rw-r--r-- | tests/stress.c | 96 | ||||
-rw-r--r-- | tests/testlib.c | 229 |
3 files changed, 133 insertions, 247 deletions
diff --git a/tests/libusb_testlib.h b/tests/libusb_testlib.h index 6c987d3..b3dbaae 100644 --- a/tests/libusb_testlib.h +++ b/tests/libusb_testlib.h @@ -20,18 +20,6 @@ #ifndef LIBUSB_TESTLIB_H #define LIBUSB_TESTLIB_H -#include <stdio.h> - -#if !defined(bool) -#define bool int -#endif -#if !defined(true) -#define true (1 == 1) -#endif -#if !defined(false) -#define false (!true) -#endif - /** Values returned from a test function to indicate test result */ typedef enum { /** Indicates that the test ran successfully. */ @@ -41,53 +29,33 @@ typedef enum { /** Indicates that an unexpected error occurred. */ TEST_STATUS_ERROR, /** Indicates that the test can't be run. For example this may be - * due to no suitable device being connected to perform the tests.*/ + * due to no suitable device being connected to perform the tests. */ TEST_STATUS_SKIP } libusb_testlib_result; /** - * Context for test library functions - */ -typedef struct { - char ** test_names; - int test_count; - bool list_tests; - bool verbose; - int old_stdout; - int old_stderr; - FILE* output_file; - int null_fd; -} libusb_testlib_ctx; - -/** * Logs some test information or state */ -void libusb_testlib_logf(libusb_testlib_ctx * ctx, - const char* fmt, ...); - -/** - * Function pointer for a libusb test function. - * - * Should return TEST_STATUS_SUCCESS on success or another TEST_STATUS value. - */ -typedef libusb_testlib_result -(*libusb_testlib_test_function)(libusb_testlib_ctx * ctx); +void libusb_testlib_logf(const char *fmt, ...); /** * Structure holding a test description. */ typedef struct { /** Human readable name of the test. */ - const char * name; - /** The test library will call this function to run the test. */ - libusb_testlib_test_function function; + const char *name; + /** The test library will call this function to run the test. + * + * Should return TEST_STATUS_SUCCESS on success or another TEST_STATUS value. + */ + libusb_testlib_result (*function)(void); } libusb_testlib_test; /** * Value to use at the end of a test array to indicate the last * element. */ -#define LIBUSB_NULL_TEST {NULL, NULL} +#define LIBUSB_NULL_TEST { NULL, NULL } /** * Runs the tests provided. @@ -100,8 +68,7 @@ typedef struct { * \param tests A NULL_TEST terminated array of tests * \return 0 on success, non-zero on failure */ -int libusb_testlib_run_tests(int argc, - char ** argv, - const libusb_testlib_test * tests); +int libusb_testlib_run_tests(int argc, char *argv[], + const libusb_testlib_test *tests); #endif //LIBUSB_TESTLIB_H diff --git a/tests/stress.c b/tests/stress.c index 1602ee9..5c8c315 100644 --- a/tests/stress.c +++ b/tests/stress.c @@ -17,111 +17,114 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <stdio.h> #include <string.h> -#include <memory.h> #include "libusb.h" #include "libusb_testlib.h" /** Test that creates and destroys a single concurrent context * 10000 times. */ -static libusb_testlib_result test_init_and_exit(libusb_testlib_ctx * tctx) +static libusb_testlib_result test_init_and_exit(void) { - libusb_context * ctx = NULL; - int i; - for (i = 0; i < 10000; ++i) { - int r = libusb_init(&ctx); + for (int i = 0; i < 10000; ++i) { + libusb_context *ctx = NULL; + int r; + + r = libusb_init(&ctx); if (r != LIBUSB_SUCCESS) { - libusb_testlib_logf(tctx, + libusb_testlib_logf( "Failed to init libusb on iteration %d: %d", i, r); return TEST_STATUS_FAILURE; } libusb_exit(ctx); - ctx = NULL; } return TEST_STATUS_SUCCESS; } /** Tests that devices can be listed 1000 times. */ -static libusb_testlib_result test_get_device_list(libusb_testlib_ctx * tctx) +static libusb_testlib_result test_get_device_list(void) { - libusb_context * ctx = NULL; - int r, i; + libusb_context *ctx; + int r; + r = libusb_init(&ctx); if (r != LIBUSB_SUCCESS) { - libusb_testlib_logf(tctx, "Failed to init libusb: %d", r); + libusb_testlib_logf("Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; } - for (i = 0; i < 1000; ++i) { - libusb_device ** device_list; + + for (int i = 0; i < 1000; ++i) { + libusb_device **device_list = NULL; ssize_t list_size = libusb_get_device_list(ctx, &device_list); - if (list_size < 0 || device_list == NULL) { - libusb_testlib_logf(tctx, + if (list_size < 0 || !device_list) { + libusb_testlib_logf( "Failed to get device list on iteration %d: %ld (%p)", i, (long)-list_size, device_list); + libusb_exit(ctx); return TEST_STATUS_FAILURE; } libusb_free_device_list(device_list, 1); } + libusb_exit(ctx); return TEST_STATUS_SUCCESS; } /** Tests that 100 concurrent device lists can be open at a time. */ -static libusb_testlib_result test_many_device_lists(libusb_testlib_ctx * tctx) +static libusb_testlib_result test_many_device_lists(void) { #define LIST_COUNT 100 - libusb_context * ctx = NULL; - libusb_device ** device_lists[LIST_COUNT]; - int r, i; - memset(device_lists, 0, sizeof(device_lists)); + libusb_testlib_result result = TEST_STATUS_SUCCESS; + libusb_context *ctx = NULL; + libusb_device **device_lists[LIST_COUNT]; + int r; r = libusb_init(&ctx); if (r != LIBUSB_SUCCESS) { - libusb_testlib_logf(tctx, "Failed to init libusb: %d", r); + libusb_testlib_logf("Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; } + memset(device_lists, 0, sizeof(device_lists)); + /* Create the 100 device lists. */ - for (i = 0; i < LIST_COUNT; ++i) { - ssize_t list_size = libusb_get_device_list(ctx, &(device_lists[i])); - if (list_size < 0 || device_lists[i] == NULL) { - libusb_testlib_logf(tctx, - "Failed to get device list on iteration %d: %d (%p)", - i, -list_size, device_lists[i]); - return TEST_STATUS_FAILURE; + for (int i = 0; i < LIST_COUNT; ++i) { + ssize_t list_size = libusb_get_device_list(ctx, &device_lists[i]); + if (list_size < 0 || !device_lists[i]) { + libusb_testlib_logf( + "Failed to get device list on iteration %d: %ld (%p)", + i, (long)-list_size, device_lists[i]); + result = TEST_STATUS_FAILURE; + break; } } /* Destroy the 100 device lists. */ - for (i = 0; i < LIST_COUNT; ++i) { - if (device_lists[i]) { + for (int i = 0; i < LIST_COUNT; ++i) { + if (device_lists[i]) libusb_free_device_list(device_lists[i], 1); - device_lists[i] = NULL; - } } libusb_exit(ctx); - return TEST_STATUS_SUCCESS; + return result; #undef LIST_COUNT } /** Tests that the default context (used for various things including * logging) works correctly when the first context created in a * process is destroyed. */ -static libusb_testlib_result test_default_context_change(libusb_testlib_ctx * tctx) +static libusb_testlib_result test_default_context_change(void) { - libusb_context * ctx = NULL; - int r, i; + for (int i = 0; i < 100; ++i) { + libusb_context *ctx = NULL; + int r; - for (i = 0; i < 100; ++i) { /* First create a new context */ r = libusb_init(&ctx); if (r != LIBUSB_SUCCESS) { - libusb_testlib_logf(tctx, "Failed to init libusb: %d", r); + libusb_testlib_logf("Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; } @@ -132,7 +135,8 @@ static libusb_testlib_result test_default_context_change(libusb_testlib_ctx * tc /* Now create a reference to the default context */ r = libusb_init(NULL); if (r != LIBUSB_SUCCESS) { - libusb_testlib_logf(tctx, "Failed to init libusb: %d", r); + libusb_testlib_logf("Failed to init libusb: %d", r); + libusb_exit(ctx); return TEST_STATUS_FAILURE; } @@ -147,14 +151,14 @@ static libusb_testlib_result test_default_context_change(libusb_testlib_ctx * tc /* Fill in the list of tests. */ static const libusb_testlib_test tests[] = { - {"init_and_exit", &test_init_and_exit}, - {"get_device_list", &test_get_device_list}, - {"many_device_lists", &test_many_device_lists}, - {"default_context_change", &test_default_context_change}, + { "init_and_exit", &test_init_and_exit }, + { "get_device_list", &test_get_device_list }, + { "many_device_lists", &test_many_device_lists }, + { "default_context_change", &test_default_context_change }, LIBUSB_NULL_TEST }; -int main (int argc, char ** argv) +int main(int argc, char *argv[]) { return libusb_testlib_run_tests(argc, argv, tests); } diff --git a/tests/testlib.c b/tests/testlib.c index 95c9c0a..fb4fee6 100644 --- a/tests/testlib.c +++ b/tests/testlib.c @@ -19,35 +19,22 @@ #include "libusb_testlib.h" -#include <stdio.h> +#include <errno.h> #include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> #include <string.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> #if defined(_WIN32) -#include <io.h> -#define dup _dup -#define dup2 _dup2 -#define open _open -#define close _close -#define fdopen _fdopen #define NULL_PATH "nul" -#define STDOUT_FILENO 1 -#define STDERR_FILENO 2 #else -#include <unistd.h> #define NULL_PATH "/dev/null" #endif -#define INVALID_FD -1 -#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0) /** * Converts a test result code into a human readable string. */ -static const char* test_result_to_str(libusb_testlib_result result) +static const char *test_result_to_str(libusb_testlib_result result) { switch (result) { case TEST_STATUS_SUCCESS: @@ -63,96 +50,27 @@ static const char* test_result_to_str(libusb_testlib_result result) } } -static void print_usage(int argc, char ** argv) +static void print_usage(const char *progname) { - printf("Usage: %s [-l] [-v] [<test_name> ...]\n", - argc > 0 ? argv[0] : "test_*"); + printf("Usage: %s [-l] [-v] [<test_name> ...]\n", progname); printf(" -l List available tests\n"); - printf(" -v Don't redirect STDERR/STDOUT during tests\n"); + printf(" -v Don't redirect STDERR before running tests\n"); + printf(" -h Display this help and exit\n"); } -static void cleanup_test_output(libusb_testlib_ctx * ctx) -{ - if (!ctx->verbose) { - if (ctx->old_stdout != INVALID_FD) { - IGNORE_RETVAL(dup2(ctx->old_stdout, STDOUT_FILENO)); - ctx->old_stdout = INVALID_FD; - } - if (ctx->old_stderr != INVALID_FD) { - IGNORE_RETVAL(dup2(ctx->old_stderr, STDERR_FILENO)); - ctx->old_stderr = INVALID_FD; - } - if (ctx->null_fd != INVALID_FD) { - close(ctx->null_fd); - ctx->null_fd = INVALID_FD; - } - if (ctx->output_file != stdout) { - fclose(ctx->output_file); - ctx->output_file = stdout; - } - } -} - -/** - * Setup test output handles - * \return zero on success, non-zero on failure - */ -static int setup_test_output(libusb_testlib_ctx * ctx) -{ - /* Stop output to stdout and stderr from being displayed if using non-verbose output */ - if (!ctx->verbose) { - /* Keep a copy of STDOUT and STDERR */ - ctx->old_stdout = dup(STDOUT_FILENO); - if (ctx->old_stdout < 0) { - ctx->old_stdout = INVALID_FD; - printf("Failed to duplicate stdout handle: %d\n", errno); - return 1; - } - ctx->old_stderr = dup(STDERR_FILENO); - if (ctx->old_stderr < 0) { - ctx->old_stderr = INVALID_FD; - cleanup_test_output(ctx); - printf("Failed to duplicate stderr handle: %d\n", errno); - return 1; - } - /* Redirect STDOUT_FILENO and STDERR_FILENO to /dev/null or "nul"*/ - ctx->null_fd = open(NULL_PATH, O_WRONLY); - if (ctx->null_fd < 0) { - ctx->null_fd = INVALID_FD; - cleanup_test_output(ctx); - printf("Failed to open null handle: %d\n", errno); - return 1; - } - if ((dup2(ctx->null_fd, STDOUT_FILENO) < 0) || - (dup2(ctx->null_fd, STDERR_FILENO) < 0)) { - cleanup_test_output(ctx); - return 1; - } - ctx->output_file = fdopen(ctx->old_stdout, "w"); - if (!ctx->output_file) { - ctx->output_file = stdout; - cleanup_test_output(ctx); - printf("Failed to open FILE for output handle: %d\n", errno); - return 1; - } - } - return 0; -} - -void libusb_testlib_logf(libusb_testlib_ctx * ctx, - const char* fmt, ...) +void libusb_testlib_logf(const char *fmt, ...) { va_list va; + va_start(va, fmt); - vfprintf(ctx->output_file, fmt, va); + vfprintf(stdout, fmt, va); va_end(va); - fprintf(ctx->output_file, "\n"); - fflush(ctx->output_file); + fputc('\n', stdout); + fflush(stdout); } -int libusb_testlib_run_tests(int argc, - char ** argv, - const libusb_testlib_test * tests) +int libusb_testlib_run_tests(int argc, char *argv[], + const libusb_testlib_test *tests) { int run_count = 0; int idx = 0; @@ -160,108 +78,105 @@ int libusb_testlib_run_tests(int argc, int fail_count = 0; int error_count = 0; int skip_count = 0; - int r, j; - size_t arglen; - libusb_testlib_result test_result; - libusb_testlib_ctx ctx; /* Setup default mode of operation */ - ctx.test_names = NULL; - ctx.test_count = 0; - ctx.list_tests = false; - ctx.verbose = false; - ctx.old_stdout = INVALID_FD; - ctx.old_stderr = INVALID_FD; - ctx.output_file = stdout; - ctx.null_fd = INVALID_FD; + char **test_names = NULL; + int test_count = 0; + bool list_tests = false; + bool verbose = false; /* Parse command line options */ if (argc >= 2) { - for (j = 1; j < argc; j++) { - arglen = strlen(argv[j]); - if ( ((argv[j][0] == '-') || (argv[j][0] == '/')) && - arglen >=2 ) { - switch (argv[j][1]) { + for (int j = 1; j < argc; j++) { + const char *argstr = argv[j]; + size_t arglen = strlen(argstr); + + if (argstr[0] == '-' || argstr[0] == '/') { + if (arglen == 2) { + switch (argstr[1]) { case 'l': - ctx.list_tests = true; - break; + list_tests = true; + continue; case 'v': - ctx.verbose = true; - break; - default: - printf("Unknown option: '%s'\n", argv[j]); - print_usage(argc, argv); - return 1; + verbose = true; + continue; + case 'h': + print_usage(argv[0]); + return 0; } + } + + fprintf(stderr, "Unknown option: '%s'\n", argstr); + print_usage(argv[0]); + return 1; } else { /* End of command line options, remaining must be list of tests to run */ - ctx.test_names = argv + j; - ctx.test_count = argc - j; + test_names = argv + j; + test_count = argc - j; break; } } } /* Validate command line options */ - if (ctx.test_names && ctx.list_tests) { - printf("List of tests requested but test list provided\n"); - print_usage(argc, argv); + if (test_names && list_tests) { + fprintf(stderr, "List of tests requested but test list provided\n"); + print_usage(argv[0]); return 1; } /* Setup test log output */ - r = setup_test_output(&ctx); - if (r != 0) - return r; + if (!verbose) { + if (!freopen(NULL_PATH, "w", stderr)) { + printf("Failed to open null handle: %d\n", errno); + return 1; + } + } /* Act on any options not related to running tests */ - if (ctx.list_tests) { - while (tests[idx].function != NULL) { - libusb_testlib_logf(&ctx, tests[idx].name); - ++idx; - } - cleanup_test_output(&ctx); + if (list_tests) { + while (tests[idx].function) + libusb_testlib_logf("%s", tests[idx++].name); return 0; } /* Run any requested tests */ - while (tests[idx].function != NULL) { - const libusb_testlib_test * test = &tests[idx]; - ++idx; - if (ctx.test_count > 0) { + while (tests[idx].function) { + const libusb_testlib_test *test = &tests[idx++]; + libusb_testlib_result test_result; + + if (test_count > 0) { /* Filtering tests to run, check if this is one of them */ int i; - for (i = 0; i < ctx.test_count; ++i) { - if (strcmp(ctx.test_names[i], test->name) == 0) + + for (i = 0; i < test_count; i++) { + if (!strcmp(test_names[i], test->name)) /* Matches a requested test name */ break; } - if (i >= ctx.test_count) { + if (i == test_count) { /* Failed to find a test match, so do the next loop iteration */ continue; } } - libusb_testlib_logf(&ctx, - "Starting test run: %s...", test->name); - test_result = test->function(&ctx); - libusb_testlib_logf(&ctx, - "%s (%d)", - test_result_to_str(test_result), test_result); + libusb_testlib_logf("Starting test run: %s...", test->name); + test_result = test->function(); + libusb_testlib_logf("%s (%d)", test_result_to_str(test_result), test_result); switch (test_result) { case TEST_STATUS_SUCCESS: pass_count++; break; case TEST_STATUS_FAILURE: fail_count++; break; case TEST_STATUS_ERROR: error_count++; break; case TEST_STATUS_SKIP: skip_count++; break; } - ++run_count; + run_count++; } - libusb_testlib_logf(&ctx, "---"); - libusb_testlib_logf(&ctx, "Ran %d tests", run_count); - libusb_testlib_logf(&ctx, "Passed %d tests", pass_count); - libusb_testlib_logf(&ctx, "Failed %d tests", fail_count); - libusb_testlib_logf(&ctx, "Error in %d tests", error_count); - libusb_testlib_logf(&ctx, "Skipped %d tests", skip_count); - cleanup_test_output(&ctx); + libusb_testlib_logf("---"); + libusb_testlib_logf("Ran %d tests", run_count); + libusb_testlib_logf("Passed %d tests", pass_count); + libusb_testlib_logf("Failed %d tests", fail_count); + libusb_testlib_logf("Error in %d tests", error_count); + libusb_testlib_logf("Skipped %d tests", skip_count); + return pass_count != run_count; } |