~ubuntu-branches/ubuntu/saucy/libusbx/saucy-proposed

« back to all changes in this revision

Viewing changes to tests/testlib.c

  • Committer: Package Import Robot
  • Author(s): Aurelien Jarno
  • Date: 2013-05-06 17:31:43 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130506173143-wfbiltvcnn7pvdpa
Tags: 2:1.0.15-1
* New upstream version.
* Fix cross-build (closes: #694912, #705658).
* Add a -dbg package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libusbx 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 "libusbx_testlib.h"
 
21
 
 
22
#include <stdio.h>
 
23
#include <stdarg.h>
 
24
#include <string.h>
 
25
#include <errno.h>
 
26
#if !defined(_WIN32_WCE)
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
#include <fcntl.h>
 
30
#endif
 
31
 
 
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
 
36
#elif defined(_WIN32)
 
37
#include <io.h>
 
38
#define dup _dup
 
39
#define dup2 _dup2
 
40
#define open _open
 
41
#define close _close
 
42
#define fdopen _fdopen
 
43
#define NULL_PATH "nul"
 
44
#define STDOUT_FILENO 1
 
45
#define STDERR_FILENO 2
 
46
#else
 
47
#include <unistd.h>
 
48
#define NULL_PATH "/dev/null"
 
49
#endif
 
50
#define INVALID_FD -1
 
51
#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
 
52
 
 
53
/**
 
54
 * Converts a test result code into a human readable string.
 
55
 */
 
56
static const char* test_result_to_str(libusbx_testlib_result result)
 
57
{
 
58
        switch (result) {
 
59
        case TEST_STATUS_SUCCESS:
 
60
                return "Success";
 
61
        case TEST_STATUS_FAILURE:
 
62
                return "Failure";
 
63
        case TEST_STATUS_ERROR:
 
64
                return "Error";
 
65
        case TEST_STATUS_SKIP:
 
66
                return "Skip";
 
67
        default:
 
68
                return "Unknown";
 
69
        }
 
70
}
 
71
 
 
72
static void print_usage(int argc, char ** argv)
 
73
{
 
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");
 
78
}
 
79
 
 
80
static void cleanup_test_output(libusbx_testlib_ctx * ctx)
 
81
{
 
82
#ifndef DISABLE_STDOUT_REDIRECTION
 
83
        if (!ctx->verbose) {
 
84
                if (ctx->old_stdout != INVALID_FD) {
 
85
                        IGNORE_RETVAL(dup2(ctx->old_stdout, STDOUT_FILENO));
 
86
                        ctx->old_stdout = INVALID_FD;
 
87
                }
 
88
                if (ctx->old_stderr != INVALID_FD) {
 
89
                        IGNORE_RETVAL(dup2(ctx->old_stderr, STDERR_FILENO));
 
90
                        ctx->old_stderr = INVALID_FD;
 
91
                }
 
92
                if (ctx->null_fd != INVALID_FD) {
 
93
                        close(ctx->null_fd);
 
94
                        ctx->null_fd = INVALID_FD;
 
95
                }
 
96
                if (ctx->output_file != stdout) {
 
97
                        fclose(ctx->output_file);
 
98
                        ctx->output_file = stdout;
 
99
                }
 
100
        }
 
101
#endif
 
102
}
 
103
 
 
104
/**
 
105
 * Setup test output handles
 
106
 * \return zero on success, non-zero on failure
 
107
 */
 
108
static int setup_test_output(libusbx_testlib_ctx * ctx)
 
109
{
 
110
#ifndef DISABLE_STDOUT_REDIRECTION
 
111
        /* Stop output to stdout and stderr from being displayed if using non-verbose output */
 
112
        if (!ctx->verbose) {
 
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);
 
118
                        return 1;
 
119
                }
 
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);
 
125
                        return 1;
 
126
                }
 
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);
 
133
                        return 1;
 
134
                }
 
135
                if ((dup2(ctx->null_fd, STDOUT_FILENO) < 0) ||
 
136
                        (dup2(ctx->null_fd, STDERR_FILENO) < 0)) {
 
137
                                cleanup_test_output(ctx);
 
138
                                return 1;
 
139
                }
 
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);
 
144
                        return 1;
 
145
                }
 
146
        }
 
147
#endif
 
148
        return 0;
 
149
}
 
150
 
 
151
void libusbx_testlib_logf(libusbx_testlib_ctx * ctx,
 
152
        const char* fmt, ...)
 
153
{
 
154
        va_list va;
 
155
        va_start(va, fmt);
 
156
        vfprintf(ctx->output_file, fmt, va);
 
157
        va_end(va);
 
158
        fprintf(ctx->output_file, "\n");
 
159
        fflush(ctx->output_file);
 
160
}
 
161
 
 
162
int libusbx_testlib_run_tests(int argc,
 
163
        char ** argv,
 
164
        const libusbx_testlib_test * tests)
 
165
{
 
166
        int run_count = 0;
 
167
        int idx = 0;
 
168
        int pass_count = 0;
 
169
        int fail_count = 0;
 
170
        int error_count = 0;
 
171
        int skip_count = 0;
 
172
        int r, j;
 
173
        size_t arglen;
 
174
        libusbx_testlib_result test_result;
 
175
        libusbx_testlib_ctx ctx;
 
176
 
 
177
        /* Setup default mode of operation */
 
178
        ctx.test_names = NULL;
 
179
        ctx.test_count = 0;
 
180
        ctx.list_tests = false;
 
181
        ctx.verbose = false;
 
182
        ctx.old_stdout = INVALID_FD;
 
183
        ctx.old_stderr = INVALID_FD;
 
184
        ctx.output_file = stdout;
 
185
        ctx.null_fd = INVALID_FD;
 
186
 
 
187
        /* Parse command line options */
 
188
        if (argc >= 2) {
 
189
                for (j = 1; j < argc; j++) {
 
190
                        arglen = strlen(argv[j]);
 
191
                        if ( ((argv[j][0] == '-') || (argv[j][0] == '/')) &&
 
192
                                arglen >=2 ) {
 
193
                                        switch (argv[j][1]) {
 
194
                                        case 'l':
 
195
                                                ctx.list_tests = true;
 
196
                                                break;
 
197
                                        case 'v':
 
198
                                                ctx.verbose = true;
 
199
                                                break;
 
200
                                        default:
 
201
                                                printf("Unknown option: '%s'\n", argv[j]);
 
202
                                                print_usage(argc, argv);
 
203
                                                return 1;
 
204
                                        }
 
205
                        } else {
 
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;
 
209
                                break;
 
210
                        }
 
211
                }
 
212
        }
 
213
 
 
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);
 
218
                return 1;
 
219
        }
 
220
 
 
221
        /* Setup test log output */
 
222
        r = setup_test_output(&ctx);
 
223
        if (r != 0)
 
224
                return r;  
 
225
 
 
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);
 
230
                        ++idx;
 
231
                }
 
232
                cleanup_test_output(&ctx);
 
233
                return 0;
 
234
        }
 
235
 
 
236
        /* Run any requested tests */
 
237
        while (tests[idx].function != NULL) {
 
238
                const libusbx_testlib_test * test = &tests[idx];
 
239
                ++idx;
 
240
                if (ctx.test_count > 0) {
 
241
                        /* Filtering tests to run, check if this is one of them */
 
242
                        int i;
 
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 */
 
246
                                        break;
 
247
                        }
 
248
                        if (i >= ctx.test_count) {
 
249
                                /* Failed to find a test match, so do the next loop iteration */
 
250
                                continue;
 
251
                        }
 
252
                }
 
253
                libusbx_testlib_logf(&ctx,
 
254
                        "Starting test run: %s...", test->name);
 
255
                test_result = test->function(&ctx);
 
256
                libusbx_testlib_logf(&ctx,
 
257
                        "%s (%d)",
 
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;
 
264
                }
 
265
                ++run_count;
 
266
        }
 
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);
 
273
 
 
274
        cleanup_test_output(&ctx);
 
275
        return pass_count != run_count;
 
276
}