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"
51 #define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
54 * Converts a test result code into a human readable string.
56 static const char* test_result_to_str(libusbx_testlib_result result
)
59 case TEST_STATUS_SUCCESS
:
61 case TEST_STATUS_FAILURE
:
63 case TEST_STATUS_ERROR
:
65 case TEST_STATUS_SKIP
:
72 static void print_usage(int argc
, char ** argv
)
74 printf("Usage: %s [-l] [-v] [<test_name> ...]\n",
75 argc
> 0 ? argv
[0] : "test_*");
76 printf(" -l List available tests\n");
77 printf(" -v Don't redirect STDERR/STDOUT during tests\n");
80 static void cleanup_test_output(libusbx_testlib_ctx
* ctx
)
82 #ifndef DISABLE_STDOUT_REDIRECTION
84 if (ctx
->old_stdout
!= INVALID_FD
) {
85 IGNORE_RETVAL(dup2(ctx
->old_stdout
, STDOUT_FILENO
));
86 ctx
->old_stdout
= INVALID_FD
;
88 if (ctx
->old_stderr
!= INVALID_FD
) {
89 IGNORE_RETVAL(dup2(ctx
->old_stderr
, STDERR_FILENO
));
90 ctx
->old_stderr
= INVALID_FD
;
92 if (ctx
->null_fd
!= INVALID_FD
) {
94 ctx
->null_fd
= INVALID_FD
;
96 if (ctx
->output_file
!= stdout
) {
97 fclose(ctx
->output_file
);
98 ctx
->output_file
= stdout
;
105 * Setup test output handles
106 * \return zero on success, non-zero on failure
108 static int setup_test_output(libusbx_testlib_ctx
* ctx
)
110 #ifndef DISABLE_STDOUT_REDIRECTION
111 /* Stop output to stdout and stderr from being displayed if using non-verbose output */
113 /* Keep a copy of STDOUT and STDERR */
114 ctx
->old_stdout
= dup(STDOUT_FILENO
);
115 if (ctx
->old_stdout
< 0) {
116 ctx
->old_stdout
= INVALID_FD
;
117 printf("Failed to duplicate stdout handle: %d\n", errno
);
120 ctx
->old_stderr
= dup(STDERR_FILENO
);
121 if (ctx
->old_stderr
< 0) {
122 ctx
->old_stderr
= INVALID_FD
;
123 cleanup_test_output(ctx
);
124 printf("Failed to duplicate stderr handle: %d\n", errno
);
127 /* Redirect STDOUT_FILENO and STDERR_FILENO to /dev/null or "nul"*/
128 ctx
->null_fd
= open(NULL_PATH
, O_WRONLY
);
129 if (ctx
->null_fd
< 0) {
130 ctx
->null_fd
= INVALID_FD
;
131 cleanup_test_output(ctx
);
132 printf("Failed to open null handle: %d\n", errno
);
135 if ((dup2(ctx
->null_fd
, STDOUT_FILENO
) < 0) ||
136 (dup2(ctx
->null_fd
, STDERR_FILENO
) < 0)) {
137 cleanup_test_output(ctx
);
140 ctx
->output_file
= fdopen(ctx
->old_stdout
, "w");
141 if (!ctx
->output_file
) {
142 cleanup_test_output(ctx
);
143 printf("Failed to open FILE for output handle: %d\n", errno
);
151 void libusbx_testlib_logf(libusbx_testlib_ctx
* ctx
,
152 const char* fmt
, ...)
156 vfprintf(ctx
->output_file
, fmt
, va
);
158 fprintf(ctx
->output_file
, "\n");
159 fflush(ctx
->output_file
);
162 int libusbx_testlib_run_tests(int argc
,
164 const libusbx_testlib_test
* tests
)
174 libusbx_testlib_result test_result
;
175 libusbx_testlib_ctx ctx
;
177 /* Setup default mode of operation */
178 ctx
.test_names
= NULL
;
180 ctx
.list_tests
= false;
182 ctx
.old_stdout
= INVALID_FD
;
183 ctx
.old_stderr
= INVALID_FD
;
184 ctx
.output_file
= stdout
;
185 ctx
.null_fd
= INVALID_FD
;
187 /* Parse command line options */
189 for (j
= 1; j
< argc
; j
++) {
190 arglen
= strlen(argv
[j
]);
191 if ( ((argv
[j
][0] == '-') || (argv
[j
][0] == '/')) &&
193 switch (argv
[j
][1]) {
195 ctx
.list_tests
= true;
201 printf("Unknown option: '%s'\n", argv
[j
]);
202 print_usage(argc
, argv
);
206 /* End of command line options, remaining must be list of tests to run */
207 ctx
.test_names
= argv
+ j
;
208 ctx
.test_count
= argc
- j
;
214 /* Validate command line options */
215 if (ctx
.test_names
&& ctx
.list_tests
) {
216 printf("List of tests requested but test list provided\n");
217 print_usage(argc
, argv
);
221 /* Setup test log output */
222 r
= setup_test_output(&ctx
);
226 /* Act on any options not related to running tests */
227 if (ctx
.list_tests
) {
228 while (tests
[idx
].function
!= NULL
) {
229 libusbx_testlib_logf(&ctx
, tests
[idx
].name
);
232 cleanup_test_output(&ctx
);
236 /* Run any requested tests */
237 while (tests
[idx
].function
!= NULL
) {
238 const libusbx_testlib_test
* test
= &tests
[idx
];
240 if (ctx
.test_count
> 0) {
241 /* Filtering tests to run, check if this is one of them */
243 for (i
= 0; i
< ctx
.test_count
; ++i
) {
244 if (strcmp(ctx
.test_names
[i
], test
->name
) == 0)
245 /* Matches a requested test name */
248 if (i
>= ctx
.test_count
) {
249 /* Failed to find a test match, so do the next loop iteration */
253 libusbx_testlib_logf(&ctx
,
254 "Starting test run: %s...", test
->name
);
255 test_result
= test
->function(&ctx
);
256 libusbx_testlib_logf(&ctx
,
258 test_result_to_str(test_result
), test_result
);
259 switch (test_result
) {
260 case TEST_STATUS_SUCCESS
: pass_count
++; break;
261 case TEST_STATUS_FAILURE
: fail_count
++; break;
262 case TEST_STATUS_ERROR
: error_count
++; break;
263 case TEST_STATUS_SKIP
: skip_count
++; break;
267 libusbx_testlib_logf(&ctx
, "---");
268 libusbx_testlib_logf(&ctx
, "Ran %d tests", run_count
);
269 libusbx_testlib_logf(&ctx
, "Passed %d tests", pass_count
);
270 libusbx_testlib_logf(&ctx
, "Failed %d tests", fail_count
);
271 libusbx_testlib_logf(&ctx
, "Error in %d tests", error_count
);
272 libusbx_testlib_logf(&ctx
, "Skipped %d tests", skip_count
);
274 cleanup_test_output(&ctx
);
275 return pass_count
!= run_count
;