blob: 3825341c2facaba2edafc9f36d076c9a425d0d85 [file] [log] [blame]
Toby Gray21cf6e42012-11-21 14:00:31 +00001/*
hjelmn@cs.unm.edu1eff2202014-01-08 23:50:34 +00002 * libusb test library helper functions
Toby Gray21cf6e42012-11-21 14:00:31 +00003 * Copyright © 2012 Toby Gray <toby.gray@realvnc.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
Chris Dickensf2e551a2020-11-27 15:22:29 -080020#include <config.h>
Toby Gray21cf6e42012-11-21 14:00:31 +000021
Toby Gray21cf6e42012-11-21 14:00:31 +000022#include <errno.h>
Chris Dickensa016a082020-09-13 15:30:04 -070023#include <stdarg.h>
24#include <stdbool.h>
25#include <stdio.h>
26#include <string.h>
Toby Gray21cf6e42012-11-21 14:00:31 +000027
Chris Dickensf2e551a2020-11-27 15:22:29 -080028#include "libusb_testlib.h"
29
30#if defined(PLATFORM_POSIX)
Toby Gray21cf6e42012-11-21 14:00:31 +000031#define NULL_PATH "/dev/null"
Chris Dickensf2e551a2020-11-27 15:22:29 -080032#elif defined(PLATFORM_WINDOWS)
33#define NULL_PATH "nul"
Toby Gray21cf6e42012-11-21 14:00:31 +000034#endif
Toby Gray21cf6e42012-11-21 14:00:31 +000035
36/**
37 * Converts a test result code into a human readable string.
38 */
Chris Dickensa016a082020-09-13 15:30:04 -070039static const char *test_result_to_str(libusb_testlib_result result)
Toby Gray21cf6e42012-11-21 14:00:31 +000040{
41 switch (result) {
42 case TEST_STATUS_SUCCESS:
43 return "Success";
44 case TEST_STATUS_FAILURE:
45 return "Failure";
46 case TEST_STATUS_ERROR:
47 return "Error";
48 case TEST_STATUS_SKIP:
49 return "Skip";
50 default:
51 return "Unknown";
52 }
53}
54
Chris Dickensa016a082020-09-13 15:30:04 -070055static void print_usage(const char *progname)
Toby Gray21cf6e42012-11-21 14:00:31 +000056{
Chris Dickensa016a082020-09-13 15:30:04 -070057 printf("Usage: %s [-l] [-v] [<test_name> ...]\n", progname);
Toby Gray21cf6e42012-11-21 14:00:31 +000058 printf(" -l List available tests\n");
Chris Dickensa016a082020-09-13 15:30:04 -070059 printf(" -v Don't redirect STDERR before running tests\n");
60 printf(" -h Display this help and exit\n");
Toby Gray21cf6e42012-11-21 14:00:31 +000061}
62
Chris Dickensa016a082020-09-13 15:30:04 -070063void libusb_testlib_logf(const char *fmt, ...)
Toby Gray21cf6e42012-11-21 14:00:31 +000064{
65 va_list va;
Chris Dickensa016a082020-09-13 15:30:04 -070066
Toby Gray21cf6e42012-11-21 14:00:31 +000067 va_start(va, fmt);
Chris Dickensa016a082020-09-13 15:30:04 -070068 vfprintf(stdout, fmt, va);
Toby Gray21cf6e42012-11-21 14:00:31 +000069 va_end(va);
Chris Dickensa016a082020-09-13 15:30:04 -070070 fputc('\n', stdout);
71 fflush(stdout);
Toby Gray21cf6e42012-11-21 14:00:31 +000072}
73
Chris Dickensa016a082020-09-13 15:30:04 -070074int libusb_testlib_run_tests(int argc, char *argv[],
75 const libusb_testlib_test *tests)
Toby Gray21cf6e42012-11-21 14:00:31 +000076{
77 int run_count = 0;
78 int idx = 0;
79 int pass_count = 0;
80 int fail_count = 0;
81 int error_count = 0;
82 int skip_count = 0;
Toby Gray21cf6e42012-11-21 14:00:31 +000083
84 /* Setup default mode of operation */
Chris Dickensa016a082020-09-13 15:30:04 -070085 char **test_names = NULL;
86 int test_count = 0;
87 bool list_tests = false;
88 bool verbose = false;
Toby Gray21cf6e42012-11-21 14:00:31 +000089
90 /* Parse command line options */
91 if (argc >= 2) {
Chris Dickensa016a082020-09-13 15:30:04 -070092 for (int j = 1; j < argc; j++) {
93 const char *argstr = argv[j];
94 size_t arglen = strlen(argstr);
95
96 if (argstr[0] == '-' || argstr[0] == '/') {
97 if (arglen == 2) {
98 switch (argstr[1]) {
Toby Gray21cf6e42012-11-21 14:00:31 +000099 case 'l':
Chris Dickensa016a082020-09-13 15:30:04 -0700100 list_tests = true;
101 continue;
Toby Gray21cf6e42012-11-21 14:00:31 +0000102 case 'v':
Chris Dickensa016a082020-09-13 15:30:04 -0700103 verbose = true;
104 continue;
105 case 'h':
106 print_usage(argv[0]);
107 return 0;
Toby Gray21cf6e42012-11-21 14:00:31 +0000108 }
Chris Dickensa016a082020-09-13 15:30:04 -0700109 }
110
111 fprintf(stderr, "Unknown option: '%s'\n", argstr);
112 print_usage(argv[0]);
113 return 1;
Toby Gray21cf6e42012-11-21 14:00:31 +0000114 } else {
115 /* End of command line options, remaining must be list of tests to run */
Chris Dickensa016a082020-09-13 15:30:04 -0700116 test_names = argv + j;
117 test_count = argc - j;
Toby Gray21cf6e42012-11-21 14:00:31 +0000118 break;
119 }
120 }
121 }
122
123 /* Validate command line options */
Chris Dickensa016a082020-09-13 15:30:04 -0700124 if (test_names && list_tests) {
125 fprintf(stderr, "List of tests requested but test list provided\n");
126 print_usage(argv[0]);
Toby Gray21cf6e42012-11-21 14:00:31 +0000127 return 1;
128 }
129
130 /* Setup test log output */
Chris Dickensa016a082020-09-13 15:30:04 -0700131 if (!verbose) {
132 if (!freopen(NULL_PATH, "w", stderr)) {
133 printf("Failed to open null handle: %d\n", errno);
134 return 1;
135 }
136 }
Toby Gray21cf6e42012-11-21 14:00:31 +0000137
138 /* Act on any options not related to running tests */
Chris Dickensa016a082020-09-13 15:30:04 -0700139 if (list_tests) {
140 while (tests[idx].function)
141 libusb_testlib_logf("%s", tests[idx++].name);
Toby Gray21cf6e42012-11-21 14:00:31 +0000142 return 0;
143 }
144
145 /* Run any requested tests */
Chris Dickensa016a082020-09-13 15:30:04 -0700146 while (tests[idx].function) {
147 const libusb_testlib_test *test = &tests[idx++];
148 libusb_testlib_result test_result;
149
150 if (test_count > 0) {
Toby Gray21cf6e42012-11-21 14:00:31 +0000151 /* Filtering tests to run, check if this is one of them */
152 int i;
Chris Dickensa016a082020-09-13 15:30:04 -0700153
154 for (i = 0; i < test_count; i++) {
155 if (!strcmp(test_names[i], test->name))
Toby Gray21cf6e42012-11-21 14:00:31 +0000156 /* Matches a requested test name */
157 break;
158 }
Chris Dickensa016a082020-09-13 15:30:04 -0700159 if (i == test_count) {
Toby Gray21cf6e42012-11-21 14:00:31 +0000160 /* Failed to find a test match, so do the next loop iteration */
161 continue;
162 }
163 }
Chris Dickensa016a082020-09-13 15:30:04 -0700164 libusb_testlib_logf("Starting test run: %s...", test->name);
165 test_result = test->function();
166 libusb_testlib_logf("%s (%d)", test_result_to_str(test_result), test_result);
Toby Gray21cf6e42012-11-21 14:00:31 +0000167 switch (test_result) {
168 case TEST_STATUS_SUCCESS: pass_count++; break;
169 case TEST_STATUS_FAILURE: fail_count++; break;
170 case TEST_STATUS_ERROR: error_count++; break;
171 case TEST_STATUS_SKIP: skip_count++; break;
172 }
Chris Dickensa016a082020-09-13 15:30:04 -0700173 run_count++;
Toby Gray21cf6e42012-11-21 14:00:31 +0000174 }
Toby Gray21cf6e42012-11-21 14:00:31 +0000175
Chris Dickensa016a082020-09-13 15:30:04 -0700176 libusb_testlib_logf("---");
177 libusb_testlib_logf("Ran %d tests", run_count);
178 libusb_testlib_logf("Passed %d tests", pass_count);
179 libusb_testlib_logf("Failed %d tests", fail_count);
180 libusb_testlib_logf("Error in %d tests", error_count);
181 libusb_testlib_logf("Skipped %d tests", skip_count);
182
Toby Gray21cf6e42012-11-21 14:00:31 +0000183 return pass_count != run_count;
184}