Update comments in get_interface_addresses_ioctl
[tor.git] / src / ext / tinytest.c
blobf6baeeb9a56009c515d06754940f9cd54533d0d5
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.
25 #ifdef TINYTEST_LOCAL
26 #include "tinytest_local.h"
27 #endif
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
34 #ifndef NO_FORKING
36 #ifdef _WIN32
37 #include <windows.h>
38 #else
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <unistd.h>
42 #endif
44 #if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
45 #if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
46 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
47 /* Workaround for a stupid bug in OSX 10.6 */
48 #define FORK_BREAKS_GCOV
49 #include <vproc.h>
50 #endif
51 #endif
53 #endif /* !NO_FORKING */
55 #ifndef __GNUC__
56 #define __attribute__(x)
57 #endif
59 #include "tinytest.h"
60 #include "tinytest_macros.h"
62 #define LONGEST_TEST_NAME 16384
64 static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
65 static int n_ok = 0; /**< Number of tests that have passed */
66 static int n_bad = 0; /**< Number of tests that have failed. */
67 static int n_skipped = 0; /**< Number of tests that have been skipped. */
69 static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/
70 static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
71 static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
72 const char *verbosity_flag = "";
74 const struct testlist_alias_t *cfg_aliases=NULL;
76 enum outcome { SKIP=2, OK=1, FAIL=0 };
77 static enum outcome cur_test_outcome = 0;
78 const char *cur_test_prefix = NULL; /**< prefix of the current test group */
79 /** Name of the current test, if we haven't logged is yet. Used for --quiet */
80 const char *cur_test_name = NULL;
82 #ifdef _WIN32
83 /* Copy of argv[0] for win32. */
84 static char commandname[MAX_PATH+1];
85 #endif
87 static void usage(struct testgroup_t *groups, int list_groups)
88 __attribute__((noreturn));
89 static int process_test_option(struct testgroup_t *groups, const char *test);
91 static enum outcome
92 testcase_run_bare_(const struct testcase_t *testcase)
94 void *env = NULL;
95 int outcome;
96 if (testcase->setup) {
97 env = testcase->setup->setup_fn(testcase);
98 if (!env)
99 return FAIL;
100 else if (env == (void*)TT_SKIP)
101 return SKIP;
104 cur_test_outcome = OK;
105 testcase->fn(env);
106 outcome = cur_test_outcome;
108 if (testcase->setup) {
109 if (testcase->setup->cleanup_fn(testcase, env) == 0)
110 outcome = FAIL;
113 return outcome;
116 #define MAGIC_EXITCODE 42
118 #ifndef NO_FORKING
120 static enum outcome
121 testcase_run_forked_(const struct testgroup_t *group,
122 const struct testcase_t *testcase)
124 #ifdef _WIN32
125 /* Fork? On Win32? How primitive! We'll do what the smart kids do:
126 we'll invoke our own exe (whose name we recall from the command
127 line) with a command line that tells it to run just the test we
128 want, and this time without forking.
130 (No, threads aren't an option. The whole point of forking is to
131 share no state between tests.)
133 int ok;
134 char buffer[LONGEST_TEST_NAME+256];
135 STARTUPINFOA si;
136 PROCESS_INFORMATION info;
137 DWORD exitcode;
139 if (!in_tinytest_main) {
140 printf("\nERROR. On Windows, testcase_run_forked_ must be"
141 " called from within tinytest_main.\n");
142 abort();
144 if (opt_verbosity>0)
145 printf("[forking] ");
147 snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
148 commandname, verbosity_flag, group->prefix, testcase->name);
150 memset(&si, 0, sizeof(si));
151 memset(&info, 0, sizeof(info));
152 si.cb = sizeof(si);
154 ok = CreateProcessA(commandname, buffer, NULL, NULL, 0,
155 0, NULL, NULL, &si, &info);
156 if (!ok) {
157 printf("CreateProcess failed!\n");
158 return 0;
160 WaitForSingleObject(info.hProcess, INFINITE);
161 GetExitCodeProcess(info.hProcess, &exitcode);
162 CloseHandle(info.hProcess);
163 CloseHandle(info.hThread);
164 if (exitcode == 0)
165 return OK;
166 else if (exitcode == MAGIC_EXITCODE)
167 return SKIP;
168 else
169 return FAIL;
170 #else
171 int outcome_pipe[2];
172 pid_t pid;
173 (void)group;
175 if (pipe(outcome_pipe))
176 perror("opening pipe");
178 if (opt_verbosity>0)
179 printf("[forking] ");
180 pid = fork();
181 #ifdef FORK_BREAKS_GCOV
182 vproc_transaction_begin(0);
183 #endif
184 if (!pid) {
185 /* child. */
186 int test_r, write_r;
187 char b[1];
188 close(outcome_pipe[0]);
189 test_r = testcase_run_bare_(testcase);
190 assert(0<=(int)test_r && (int)test_r<=2);
191 b[0] = "NYS"[test_r];
192 write_r = (int)write(outcome_pipe[1], b, 1);
193 if (write_r != 1) {
194 perror("write outcome to pipe");
195 exit(1);
197 exit(0);
198 return FAIL; /* unreachable */
199 } else {
200 /* parent */
201 int status, r;
202 char b[1];
203 /* Close this now, so that if the other side closes it,
204 * our read fails. */
205 close(outcome_pipe[1]);
206 r = (int)read(outcome_pipe[0], b, 1);
207 if (r == 0) {
208 printf("[Lost connection!] ");
209 return 0;
210 } else if (r != 1) {
211 perror("read outcome from pipe");
213 waitpid(pid, &status, 0);
214 close(outcome_pipe[0]);
215 return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
217 #endif
220 #endif /* !NO_FORKING */
223 testcase_run_one(const struct testgroup_t *group,
224 const struct testcase_t *testcase)
226 enum outcome outcome;
228 if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) {
229 if (opt_verbosity>0)
230 printf("%s%s: %s\n",
231 group->prefix, testcase->name,
232 (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED");
233 ++n_skipped;
234 return SKIP;
237 if (opt_verbosity>0 && !opt_forked) {
238 printf("%s%s: ", group->prefix, testcase->name);
239 } else {
240 if (opt_verbosity==0) printf(".");
241 cur_test_prefix = group->prefix;
242 cur_test_name = testcase->name;
245 #ifndef NO_FORKING
246 if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
247 outcome = testcase_run_forked_(group, testcase);
248 } else {
249 #else
251 #endif
252 outcome = testcase_run_bare_(testcase);
255 if (outcome == OK) {
256 ++n_ok;
257 if (opt_verbosity>0 && !opt_forked)
258 puts(opt_verbosity==1?"OK":"");
259 } else if (outcome == SKIP) {
260 ++n_skipped;
261 if (opt_verbosity>0 && !opt_forked)
262 puts("SKIPPED");
263 } else {
264 ++n_bad;
265 if (!opt_forked)
266 printf("\n [%s FAILED]\n", testcase->name);
269 if (opt_forked) {
270 exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
271 return 1; /* unreachable */
272 } else {
273 return (int)outcome;
278 tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag)
280 int i, j;
281 size_t length = LONGEST_TEST_NAME;
282 char fullname[LONGEST_TEST_NAME];
283 int found=0;
284 if (strstr(arg, ".."))
285 length = strstr(arg,"..")-arg;
286 for (i=0; groups[i].prefix; ++i) {
287 for (j=0; groups[i].cases[j].name; ++j) {
288 struct testcase_t *testcase = &groups[i].cases[j];
289 snprintf(fullname, sizeof(fullname), "%s%s",
290 groups[i].prefix, testcase->name);
291 if (!flag) { /* Hack! */
292 printf(" %s", fullname);
293 if (testcase->flags & TT_OFF_BY_DEFAULT)
294 puts(" (Off by default)");
295 else if (testcase->flags & TT_SKIP)
296 puts(" (DISABLED)");
297 else
298 puts("");
300 if (!strncmp(fullname, arg, length)) {
301 if (set)
302 testcase->flags |= flag;
303 else
304 testcase->flags &= ~flag;
305 ++found;
309 return found;
312 static void
313 usage(struct testgroup_t *groups, int list_groups)
315 puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
316 puts(" Specify tests by name, or using a prefix ending with '..'");
317 puts(" To skip a test, prefix its name with a colon.");
318 puts(" To enable a disabled test, prefix its name with a plus.");
319 puts(" Use --list-tests for a list of tests.");
320 if (list_groups) {
321 puts("Known tests are:");
322 tinytest_set_flag_(groups, "..", 1, 0);
324 exit(0);
327 static int
328 process_test_alias(struct testgroup_t *groups, const char *test)
330 int i, j, n, r;
331 for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) {
332 if (!strcmp(cfg_aliases[i].name, test)) {
333 n = 0;
334 for (j = 0; cfg_aliases[i].tests[j]; ++j) {
335 r = process_test_option(groups, cfg_aliases[i].tests[j]);
336 if (r<0)
337 return -1;
338 n += r;
340 return n;
343 printf("No such test alias as @%s!",test);
344 return -1;
347 static int
348 process_test_option(struct testgroup_t *groups, const char *test)
350 int flag = TT_ENABLED_;
351 int n = 0;
352 if (test[0] == '@') {
353 return process_test_alias(groups, test + 1);
354 } else if (test[0] == ':') {
355 ++test;
356 flag = TT_SKIP;
357 } else if (test[0] == '+') {
358 ++test;
359 ++n;
360 if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) {
361 printf("No such test as %s!\n", test);
362 return -1;
364 } else {
365 ++n;
367 if (!tinytest_set_flag_(groups, test, 1, flag)) {
368 printf("No such test as %s!\n", test);
369 return -1;
371 return n;
374 void
375 tinytest_set_aliases(const struct testlist_alias_t *aliases)
377 cfg_aliases = aliases;
381 tinytest_main(int c, const char **v, struct testgroup_t *groups)
383 int i, j, n=0;
385 #ifdef _WIN32
386 const char *sp = strrchr(v[0], '.');
387 const char *extension = "";
388 if (!sp || stricmp(sp, ".exe"))
389 extension = ".exe"; /* Add an exe so CreateProcess will work */
390 snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension);
391 commandname[MAX_PATH]='\0';
392 #endif
393 for (i=1; i<c; ++i) {
394 if (v[i][0] == '-') {
395 if (!strcmp(v[i], "--RUNNING-FORKED")) {
396 opt_forked = 1;
397 } else if (!strcmp(v[i], "--no-fork")) {
398 opt_nofork = 1;
399 } else if (!strcmp(v[i], "--quiet")) {
400 opt_verbosity = -1;
401 verbosity_flag = "--quiet";
402 } else if (!strcmp(v[i], "--verbose")) {
403 opt_verbosity = 2;
404 verbosity_flag = "--verbose";
405 } else if (!strcmp(v[i], "--terse")) {
406 opt_verbosity = 0;
407 verbosity_flag = "--terse";
408 } else if (!strcmp(v[i], "--help")) {
409 usage(groups, 0);
410 } else if (!strcmp(v[i], "--list-tests")) {
411 usage(groups, 1);
412 } else {
413 printf("Unknown option %s. Try --help\n",v[i]);
414 return -1;
416 } else {
417 int r = process_test_option(groups, v[i]);
418 if (r<0)
419 return -1;
420 n += r;
423 if (!n)
424 tinytest_set_flag_(groups, "..", 1, TT_ENABLED_);
426 #ifdef _IONBF
427 setvbuf(stdout, NULL, _IONBF, 0);
428 #endif
430 ++in_tinytest_main;
431 for (i=0; groups[i].prefix; ++i)
432 for (j=0; groups[i].cases[j].name; ++j)
433 if (groups[i].cases[j].flags & TT_ENABLED_)
434 testcase_run_one(&groups[i],
435 &groups[i].cases[j]);
437 --in_tinytest_main;
439 if (opt_verbosity==0)
440 puts("");
442 if (n_bad)
443 printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad,
444 n_bad+n_ok,n_skipped);
445 else if (opt_verbosity >= 1)
446 printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped);
448 return (n_bad == 0) ? 0 : 1;
452 tinytest_get_verbosity_(void)
454 return opt_verbosity;
457 void
458 tinytest_set_test_failed_(void)
460 if (opt_verbosity <= 0 && cur_test_name) {
461 if (opt_verbosity==0) puts("");
462 printf("%s%s: ", cur_test_prefix, cur_test_name);
463 cur_test_name = NULL;
465 cur_test_outcome = 0;
468 void
469 tinytest_set_test_skipped_(void)
471 if (cur_test_outcome==OK)
472 cur_test_outcome = SKIP;
475 char *
476 tinytest_format_hex_(const void *val_, unsigned long len)
478 const unsigned char *val = val_;
479 char *result, *cp;
480 size_t i;
481 int ellipses = 0;
483 if (!val)
484 return strdup("null");
485 if (len > 1024) {
486 ellipses = 3;
487 len = 1024;
489 if (!(result = malloc(len*2+4)))
490 return strdup("<allocation failure>");
491 cp = result;
492 for (i=0;i<len;++i) {
493 *cp++ = "0123456789ABCDEF"[(val[i] >> 4)&0x0f];
494 *cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
496 while (ellipses--)
497 *cp++ = '.';
498 *cp = 0;
499 return result;