2 * libusbx test library helper functions
3 * Copyright © 2012 Toby Gray <toby.gray@realvnc.com>
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.
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.
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
20 #include "libusbx_testlib.h"
26 #if !defined(_WIN32_WCE)
27 #include <sys/types.h>
32 #if defined(_WIN32_WCE)
33 // No support for selective redirection of STDOUT on WinCE.
34 #define DISABLE_STDOUT_REDIRECTION
35 #define STDOUT_FILENO 1
42 #define fdopen _fdopen
43 #define NULL_PATH "nul"
44 #define STDOUT_FILENO 1
45 #define STDERR_FILENO 2
48 #define NULL_PATH "/dev/null"
53 * Converts a test result code into a human readable string.
55 static const char* test_result_to_str(libusbx_testlib_result result
)
58 case TEST_STATUS_SUCCESS
:
60 case TEST_STATUS_FAILURE
:
62 case TEST_STATUS_ERROR
:
64 case TEST_STATUS_SKIP
:
71 static void print_usage(int argc
, char ** argv
)
73 printf("Usage: %s [-l] [-v] [<test_name> ...]\n",
74 argc
> 0 ? argv
[0] : "test_*");
75 printf(" -l List available tests\n");
76 printf(" -v Don't redirect STDERR/STDOUT during tests\n");
79 static void cleanup_test_output(libusbx_testlib_ctx
* ctx
)
81 #ifndef DISABLE_STDOUT_REDIRECTION
82 if (ctx
->output_file
!= NULL
) {
83 fclose(ctx
->output_file
);
84 ctx
->output_file
= NULL
;
86 if (ctx
->output_fd
!= INVALID_FD
) {
87 close(ctx
->output_fd
);
88 ctx
->output_fd
= INVALID_FD
;
90 if (ctx
->null_fd
!= INVALID_FD
) {
92 ctx
->null_fd
= INVALID_FD
;
98 * Setup test output handles
99 * \return zero on success, non-zero on failure
101 static int setup_test_output(libusbx_testlib_ctx
* ctx
)
103 #ifdef DISABLE_STDOUT_REDIRECTION
104 ctx
->output_fd
= STDOUT_FILENO
;
105 ctx
->output_file
= stdout
;
108 /* Keep a copy of STDOUT for test output */
109 ctx
->output_fd
= dup(STDOUT_FILENO
);
110 if (ctx
->output_fd
< 0) {
111 ctx
->output_fd
= INVALID_FD
;
112 printf("Failed to duplicate output handle: %d\n", errno
);
115 ctx
->output_file
= fdopen(ctx
->output_fd
, "w");
116 if (!ctx
->output_file
) {
117 cleanup_test_output(ctx
);
118 printf("Failed to open FILE for output handle: %d\n", errno
);
121 /* Stop output to stdout and stderr from being displayed if using non-verbose output */
123 /* Redirect STDOUT_FILENO and STDERR_FILENO to /dev/null or "nul"*/
124 ctx
->null_fd
= open(NULL_PATH
, O_WRONLY
);
125 if (ctx
->null_fd
< 0) {
126 ctx
->null_fd
= INVALID_FD
;
127 cleanup_test_output(ctx
);
128 printf("Failed to open null handle: %d\n", errno
);
131 if ((dup2(ctx
->null_fd
, STDOUT_FILENO
) < 0) ||
132 (dup2(ctx
->null_fd
, STDERR_FILENO
) < 0)) {
133 cleanup_test_output(ctx
);
141 void libusbx_testlib_logf(libusbx_testlib_ctx
* ctx
,
142 const char* fmt
, ...)
145 if (!ctx
->output_file
)
148 vfprintf(ctx
->output_file
, fmt
, va
);
150 fprintf(ctx
->output_file
, "\n");
151 fflush(ctx
->output_file
);
154 int libusbx_testlib_run_tests(int argc
,
156 const libusbx_testlib_test
* tests
)
166 libusbx_testlib_result test_result
;
167 libusbx_testlib_ctx ctx
;
169 /* Setup default mode of operation */
170 ctx
.test_names
= NULL
;
172 ctx
.list_tests
= false;
174 ctx
.output_fd
= INVALID_FD
;
175 ctx
.output_file
= NULL
;
176 ctx
.null_fd
= INVALID_FD
;
178 /* Parse command line options */
180 for (j
= 1; j
< argc
; j
++) {
181 arglen
= strlen(argv
[j
]);
182 if ( ((argv
[j
][0] == '-') || (argv
[j
][0] == '/')) &&
184 switch (argv
[j
][1]) {
186 ctx
.list_tests
= true;
192 printf("Unknown option: '%s'\n", argv
[j
]);
193 print_usage(argc
, argv
);
197 /* End of command line options, remaining must be list of tests to run */
198 ctx
.test_names
= argv
+ j
;
199 ctx
.test_count
= argc
- j
;
205 /* Validate command line options */
206 if (ctx
.test_names
&& ctx
.list_tests
) {
207 printf("List of tests requested but test list provided\n");
208 print_usage(argc
, argv
);
212 /* Setup test log output */
213 r
= setup_test_output(&ctx
);
217 /* Act on any options not related to running tests */
218 if (ctx
.list_tests
) {
219 while (tests
[idx
].function
!= NULL
) {
220 libusbx_testlib_logf(&ctx
, tests
[idx
].name
);
223 cleanup_test_output(&ctx
);
227 /* Run any requested tests */
228 while (tests
[idx
].function
!= NULL
) {
229 const libusbx_testlib_test
* test
= &tests
[idx
];
231 if (ctx
.test_count
> 0) {
232 /* Filtering tests to run, check if this is one of them */
234 for (i
= 0; i
< ctx
.test_count
; ++i
) {
235 if (strcmp(ctx
.test_names
[i
], test
->name
) == 0)
236 /* Matches a requested test name */
239 if (i
>= ctx
.test_count
) {
240 /* Failed to find a test match, so do the next loop iteration */
244 libusbx_testlib_logf(&ctx
,
245 "Starting test run: %s...", test
->name
);
246 test_result
= test
->function(&ctx
);
247 libusbx_testlib_logf(&ctx
,
249 test_result_to_str(test_result
), test_result
);
250 switch (test_result
) {
251 case TEST_STATUS_SUCCESS
: pass_count
++; break;
252 case TEST_STATUS_FAILURE
: fail_count
++; break;
253 case TEST_STATUS_ERROR
: error_count
++; break;
254 case TEST_STATUS_SKIP
: skip_count
++; break;
258 libusbx_testlib_logf(&ctx
, "---");
259 libusbx_testlib_logf(&ctx
, "Ran %d tests", run_count
);
260 libusbx_testlib_logf(&ctx
, "Passed %d tests", pass_count
);
261 libusbx_testlib_logf(&ctx
, "Failed %d tests", fail_count
);
262 libusbx_testlib_logf(&ctx
, "Error in %d tests", error_count
);
263 libusbx_testlib_logf(&ctx
, "Skipped %d tests", skip_count
);
265 cleanup_test_output(&ctx
);
266 return pass_count
!= run_count
;