ipc/chromium/src/third_party/libevent/test/tinytest.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial