Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnscrypt / src / libevent / test / tinytest.c
blob065bd6234f434b9a7ac7b221595c60011f81d4a0
1 /* tinytest.c -- Copyright 2009-2012 Nick Mathewson
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 * 1. Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * 3. The name of the author may not be used to endorse or promote products
12 * derived from this software without specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
31 #ifdef TINYTEST_LOCAL
32 #include "tinytest_local.h"
33 #endif
35 #ifdef WIN32
36 #include <windows.h>
37 #else
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
41 #endif
43 #if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
44 #if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
45 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
46 /* Workaround for a stupid bug in OSX 10.6 */
47 #define FORK_BREAKS_GCOV
48 #include <vproc.h>
49 #endif
50 #endif
52 #ifndef __GNUC__
53 #define __attribute__(x)
54 #endif
56 #include "tinytest.h"
57 #include "tinytest_macros.h"
59 #define LONGEST_TEST_NAME 16384
61 static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
62 static int n_ok = 0; /**< Number of tests that have passed */
63 static int n_bad = 0; /**< Number of tests that have failed. */
64 static int n_skipped = 0; /**< Number of tests that have been skipped. */
66 static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/
67 static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
68 static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
69 const char *verbosity_flag = "";
71 enum outcome { SKIP=2, OK=1, FAIL=0 };
72 static enum outcome cur_test_outcome = 0;
73 const char *cur_test_prefix = NULL; /**< prefix of the current test group */
74 /** Name of the current test, if we haven't logged is yet. Used for --quiet */
75 const char *cur_test_name = NULL;
77 #ifdef WIN32
78 /* Copy of argv[0] for win32. */
79 static char commandname[MAX_PATH+1];
80 #endif
82 static void usage(struct testgroup_t *groups, int list_groups)
83 __attribute__((noreturn));
85 static enum outcome
86 _testcase_run_bare(const struct testcase_t *testcase)
88 void *env = NULL;
89 int outcome;
90 if (testcase->setup) {
91 env = testcase->setup->setup_fn(testcase);
92 if (!env)
93 return FAIL;
94 else if (env == (void*)TT_SKIP)
95 return SKIP;
98 cur_test_outcome = OK;
99 testcase->fn(env);
100 outcome = cur_test_outcome;
102 if (testcase->setup) {
103 if (testcase->setup->cleanup_fn(testcase, env) == 0)
104 outcome = FAIL;
107 return outcome;
110 #define MAGIC_EXITCODE 42
112 static enum outcome
113 _testcase_run_forked(const struct testgroup_t *group,
114 const struct testcase_t *testcase)
116 #ifdef WIN32
117 /* Fork? On Win32? How primitive! We'll do what the smart kids do:
118 we'll invoke our own exe (whose name we recall from the command
119 line) with a command line that tells it to run just the test we
120 want, and this time without forking.
122 (No, threads aren't an option. The whole point of forking is to
123 share no state between tests.)
125 int ok;
126 char buffer[LONGEST_TEST_NAME+256];
127 STARTUPINFOA si;
128 PROCESS_INFORMATION info;
129 DWORD exitcode;
131 if (!in_tinytest_main) {
132 printf("\nERROR. On Windows, _testcase_run_forked must be"
133 " called from within tinytest_main.\n");
134 abort();
136 if (opt_verbosity>0)
137 printf("[forking] ");
139 snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
140 commandname, verbosity_flag, group->prefix, testcase->name);
142 memset(&si, 0, sizeof(si));
143 memset(&info, 0, sizeof(info));
144 si.cb = sizeof(si);
146 ok = CreateProcessA(commandname, buffer, NULL, NULL, 0,
147 0, NULL, NULL, &si, &info);
148 if (!ok) {
149 printf("CreateProcess failed!\n");
150 return 0;
152 WaitForSingleObject(info.hProcess, INFINITE);
153 GetExitCodeProcess(info.hProcess, &exitcode);
154 CloseHandle(info.hProcess);
155 CloseHandle(info.hThread);
156 if (exitcode == 0)
157 return OK;
158 else if (exitcode == MAGIC_EXITCODE)
159 return SKIP;
160 else
161 return FAIL;
162 #else
163 int outcome_pipe[2];
164 pid_t pid;
165 (void)group;
167 if (pipe(outcome_pipe))
168 perror("opening pipe");
170 if (opt_verbosity>0)
171 printf("[forking] ");
172 pid = fork();
173 #ifdef FORK_BREAKS_GCOV
174 vproc_transaction_begin(0);
175 #endif
176 if (!pid) {
177 /* child. */
178 int test_r, write_r;
179 char b[1];
180 close(outcome_pipe[0]);
181 test_r = _testcase_run_bare(testcase);
182 assert(0<=(int)test_r && (int)test_r<=2);
183 b[0] = "NYS"[test_r];
184 write_r = (int)write(outcome_pipe[1], b, 1);
185 if (write_r != 1) {
186 perror("write outcome to pipe");
187 exit(1);
189 exit(0);
190 return FAIL; /* unreachable */
191 } else {
192 /* parent */
193 int status, r;
194 char b[1];
195 /* Close this now, so that if the other side closes it,
196 * our read fails. */
197 close(outcome_pipe[1]);
198 r = (int)read(outcome_pipe[0], b, 1);
199 if (r == 0) {
200 printf("[Lost connection!] ");
201 return 0;
202 } else if (r != 1) {
203 perror("read outcome from pipe");
205 waitpid(pid, &status, 0);
206 close(outcome_pipe[0]);
207 return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
209 #endif
213 testcase_run_one(const struct testgroup_t *group,
214 const struct testcase_t *testcase)
216 enum outcome outcome;
218 if (testcase->flags & TT_SKIP) {
219 if (opt_verbosity>0)
220 printf("%s%s: SKIPPED\n",
221 group->prefix, testcase->name);
222 ++n_skipped;
223 return SKIP;
226 if (opt_verbosity>0 && !opt_forked) {
227 printf("%s%s: ", group->prefix, testcase->name);
228 } else {
229 if (opt_verbosity==0) printf(".");
230 cur_test_prefix = group->prefix;
231 cur_test_name = testcase->name;
234 if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
235 outcome = _testcase_run_forked(group, testcase);
236 } else {
237 outcome = _testcase_run_bare(testcase);
240 if (outcome == OK) {
241 ++n_ok;
242 if (opt_verbosity>0 && !opt_forked)
243 puts(opt_verbosity==1?"OK":"");
244 } else if (outcome == SKIP) {
245 ++n_skipped;
246 if (opt_verbosity>0 && !opt_forked)
247 puts("SKIPPED");
248 } else {
249 ++n_bad;
250 if (!opt_forked)
251 printf("\n [%s FAILED]\n", testcase->name);
254 if (opt_forked) {
255 exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
256 return 1; /* unreachable */
257 } else {
258 return (int)outcome;
263 _tinytest_set_flag(struct testgroup_t *groups, const char *arg, unsigned long flag)
265 int i, j;
266 size_t length = LONGEST_TEST_NAME;
267 char fullname[LONGEST_TEST_NAME];
268 int found=0;
269 if (strstr(arg, ".."))
270 length = strstr(arg,"..")-arg;
271 for (i=0; groups[i].prefix; ++i) {
272 for (j=0; groups[i].cases[j].name; ++j) {
273 snprintf(fullname, sizeof(fullname), "%s%s",
274 groups[i].prefix, groups[i].cases[j].name);
275 if (!flag) /* Hack! */
276 printf(" %s\n", fullname);
277 if (!strncmp(fullname, arg, length)) {
278 groups[i].cases[j].flags |= flag;
279 ++found;
283 return found;
286 static void
287 usage(struct testgroup_t *groups, int list_groups)
289 puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
290 puts(" Specify tests by name, or using a prefix ending with '..'");
291 puts(" To skip a test, list give its name prefixed with a colon.");
292 puts(" Use --list-tests for a list of tests.");
293 if (list_groups) {
294 puts("Known tests are:");
295 _tinytest_set_flag(groups, "..", 0);
297 exit(0);
301 tinytest_main(int c, const char **v, struct testgroup_t *groups)
303 int i, j, n=0;
305 #ifdef WIN32
306 const char *sp = strrchr(v[0], '.');
307 const char *extension = "";
308 if (!sp || stricmp(sp, ".exe"))
309 extension = ".exe"; /* Add an exe so CreateProcess will work */
310 snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension);
311 commandname[MAX_PATH]='\0';
312 #endif
313 for (i=1; i<c; ++i) {
314 if (v[i][0] == '-') {
315 if (!strcmp(v[i], "--RUNNING-FORKED")) {
316 opt_forked = 1;
317 } else if (!strcmp(v[i], "--no-fork")) {
318 opt_nofork = 1;
319 } else if (!strcmp(v[i], "--quiet")) {
320 opt_verbosity = -1;
321 verbosity_flag = "--quiet";
322 } else if (!strcmp(v[i], "--verbose")) {
323 opt_verbosity = 2;
324 verbosity_flag = "--verbose";
325 } else if (!strcmp(v[i], "--terse")) {
326 opt_verbosity = 0;
327 verbosity_flag = "--terse";
328 } else if (!strcmp(v[i], "--help")) {
329 usage(groups, 0);
330 } else if (!strcmp(v[i], "--list-tests")) {
331 usage(groups, 1);
332 } else {
333 printf("Unknown option %s. Try --help\n",v[i]);
334 return -1;
336 } else {
337 const char *test = v[i];
338 int flag = _TT_ENABLED;
339 if (test[0] == ':') {
340 ++test;
341 flag = TT_SKIP;
342 } else {
343 ++n;
345 if (!_tinytest_set_flag(groups, test, flag)) {
346 printf("No such test as %s!\n", v[i]);
347 return -1;
351 if (!n)
352 _tinytest_set_flag(groups, "..", _TT_ENABLED);
354 setvbuf(stdout, NULL, _IONBF, 0);
356 ++in_tinytest_main;
357 for (i=0; groups[i].prefix; ++i)
358 for (j=0; groups[i].cases[j].name; ++j)
359 if (groups[i].cases[j].flags & _TT_ENABLED)
360 testcase_run_one(&groups[i],
361 &groups[i].cases[j]);
363 --in_tinytest_main;
365 if (opt_verbosity==0)
366 puts("");
368 if (n_bad)
369 printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad,
370 n_bad+n_ok,n_skipped);
371 else if (opt_verbosity >= 1)
372 printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped);
374 return (n_bad == 0) ? 0 : 1;
378 _tinytest_get_verbosity(void)
380 return opt_verbosity;
383 void
384 _tinytest_set_test_failed(void)
386 if (opt_verbosity <= 0 && cur_test_name) {
387 if (opt_verbosity==0) puts("");
388 printf("%s%s: ", cur_test_prefix, cur_test_name);
389 cur_test_name = NULL;
391 cur_test_outcome = 0;
394 void
395 _tinytest_set_test_skipped(void)
397 if (cur_test_outcome==OK)
398 cur_test_outcome = SKIP;