1 /*
2 * libusb test library helper functions
3 * 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
20 #include <config.h>
21
22 #include <errno.h>
23 #include <stdarg.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "libusb_testlib.h"
29
30 #if defined(PLATFORM_POSIX)
31 #define NULL_PATH "/dev/null"
32 #elif defined(PLATFORM_WINDOWS)
33 #define NULL_PATH "nul"
34 #endif
35
36 /**
37 * Converts a test result code into a human readable string.
38 */
test_result_to_str(libusb_testlib_result result)39 static const char *test_result_to_str(libusb_testlib_result result)
40 {
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
print_usage(const char * progname)55 static void print_usage(const char *progname)
56 {
57 printf("Usage: %s [-l] [-v] [<test_name> ...]\n", progname);
58 printf(" -l List available tests\n");
59 printf(" -v Don't redirect STDERR before running tests\n");
60 printf(" -h Display this help and exit\n");
61 }
62
libusb_testlib_logf(const char * fmt,...)63 void libusb_testlib_logf(const char *fmt, ...)
64 {
65 va_list va;
66
67 va_start(va, fmt);
68 vfprintf(stdout, fmt, va);
69 va_end(va);
70 fputc('\n', stdout);
71 fflush(stdout);
72 }
73
libusb_testlib_run_tests(int argc,char * argv[],const libusb_testlib_test * tests)74 int libusb_testlib_run_tests(int argc, char *argv[],
75 const libusb_testlib_test *tests)
76 {
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;
83
84 /* Setup default mode of operation */
85 char **test_names = NULL;
86 int test_count = 0;
87 bool list_tests = false;
88 bool verbose = false;
89
90 /* Parse command line options */
91 if (argc >= 2) {
92 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]) {
99 case 'l':
100 list_tests = true;
101 continue;
102 case 'v':
103 verbose = true;
104 continue;
105 case 'h':
106 print_usage(argv[0]);
107 return 0;
108 }
109 }
110
111 fprintf(stderr, "Unknown option: '%s'\n", argstr);
112 print_usage(argv[0]);
113 return 1;
114 } else {
115 /* End of command line options, remaining must be list of tests to run */
116 test_names = argv + j;
117 test_count = argc - j;
118 break;
119 }
120 }
121 }
122
123 /* Validate command line options */
124 if (test_names && list_tests) {
125 fprintf(stderr, "List of tests requested but test list provided\n");
126 print_usage(argv[0]);
127 return 1;
128 }
129
130 /* Setup test log output */
131 if (!verbose) {
132 if (!freopen(NULL_PATH, "w", stderr)) {
133 printf("Failed to open null handle: %d\n", errno);
134 return 1;
135 }
136 }
137
138 /* Act on any options not related to running tests */
139 if (list_tests) {
140 while (tests[idx].function)
141 libusb_testlib_logf("%s", tests[idx++].name);
142 return 0;
143 }
144
145 /* Run any requested tests */
146 while (tests[idx].function) {
147 const libusb_testlib_test *test = &tests[idx++];
148 libusb_testlib_result test_result;
149
150 if (test_count > 0) {
151 /* Filtering tests to run, check if this is one of them */
152 int i;
153
154 for (i = 0; i < test_count; i++) {
155 if (!strcmp(test_names[i], test->name))
156 /* Matches a requested test name */
157 break;
158 }
159 if (i == test_count) {
160 /* Failed to find a test match, so do the next loop iteration */
161 continue;
162 }
163 }
164 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);
167 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 }
173 run_count++;
174 }
175
176 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
183 return pass_count != run_count;
184 }
185