• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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