/** 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) { libusb_context * ctx = NULL; int r, i; 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); return TEST_STATUS_FAILURE; } /* Enable debug output, to be sure to use the context */ libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG); libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_DEBUG); /* 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); return TEST_STATUS_FAILURE; } /* Destroy the first context */ libusb_exit(ctx); /* Destroy the default context */ libusb_exit(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) { libusb_context * ctx = NULL; int r, i; r = libusb_init(&ctx); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf(tctx, "Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; } for (i = 0; i < 1000; ++i) { libusb_device ** device_list; ssize_t list_size = libusb_get_device_list(ctx, &device_list); if (list_size < 0 || device_list == NULL) { libusb_testlib_logf(tctx, "Failed to get device list on iteration %d: %d (%p)", i, -list_size, device_list); 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) { #define LIST_COUNT 100 libusb_context * ctx = NULL; libusb_device ** device_lists[LIST_COUNT]; int r, i; memset(device_lists, 0, sizeof(device_lists)); r = libusb_init(&ctx); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf(tctx, "Failed to init libusb: %d", r); return TEST_STATUS_FAILURE; } /* 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; } } /* Destroy the 100 device lists. */ for (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; #undef LIST_COUNT }
/** Test that creates and destroys a single concurrent context * 10000 times. */ static libusb_testlib_result test_init_and_exit(libusb_testlib_ctx * tctx) { libusb_context * ctx = NULL; int i; for (i = 0; i < 10000; ++i) { int r = libusb_init(&ctx); if (r != LIBUSB_SUCCESS) { libusb_testlib_logf(tctx, "Failed to init libusb on iteration %d: %d", i, r); return TEST_STATUS_FAILURE; } libusb_exit(ctx); ctx = NULL; } return TEST_STATUS_SUCCESS; }
int libusb_testlib_run_tests(int argc, char ** argv, const libusb_testlib_test * tests) { int run_count = 0; int idx = 0; int pass_count = 0; 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; /* 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]) { case 'l': ctx.list_tests = true; break; case 'v': ctx.verbose = true; break; default: printf("Unknown option: '%s'\n", argv[j]); print_usage(argc, argv); 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; 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); return 1; } /* Setup test log output */ r = setup_test_output(&ctx); if (r != 0) return r; /* 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); return 0; } /* Run any requested tests */ while (tests[idx].function != NULL) { const libusb_testlib_test * test = &tests[idx]; ++idx; if (ctx.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) /* Matches a requested test name */ break; } if (i >= ctx.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); 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; } 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); return pass_count != run_count; }