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.

     1 /* tinytest.c -- Copyright 2009-2012 Nick Mathewson
     2  *
     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.
    13  *
    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.
    24  */
    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)
    87 {
    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;
    96 	}
    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;
   105 	}
   107 	return outcome;
   108 }
   110 #define MAGIC_EXITCODE 42
   112 static enum outcome
   113 _testcase_run_forked(const struct testgroup_t *group,
   114 		     const struct testcase_t *testcase)
   115 {
   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.)
   124 	 */
   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();
   135 	}
   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;
   151 	}
   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);
   188 		}
   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");
   204 		}
   205 		waitpid(pid, &status, 0);
   206 		close(outcome_pipe[0]);
   207 		return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
   208 	}
   209 #endif
   210 }
   212 int
   213 testcase_run_one(const struct testgroup_t *group,
   214 		 const struct testcase_t *testcase)
   215 {
   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;
   224 	}
   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;
   232 	}
   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);
   238 	}
   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);
   252 	}
   254 	if (opt_forked) {
   255 		exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
   256 		return 1; /* unreachable */
   257 	} else {
   258 		return (int)outcome;
   259 	}
   260 }
   262 int
   263 _tinytest_set_flag(struct testgroup_t *groups, const char *arg, unsigned long flag)
   264 {
   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;
   280 			}
   281 		}
   282 	}
   283 	return found;
   284 }
   286 static void
   287 usage(struct testgroup_t *groups, int list_groups)
   288 {
   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);
   296 	}
   297 	exit(0);
   298 }
   300 int
   301 tinytest_main(int c, const char **v, struct testgroup_t *groups)
   302 {
   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;
   335 			}
   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;
   344 			}
   345 			if (!_tinytest_set_flag(groups, test, flag)) {
   346 				printf("No such test as %s!\n", v[i]);
   347 				return -1;
   348 			}
   349 		}
   350 	}
   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;
   375 }
   377 int
   378 _tinytest_get_verbosity(void)
   379 {
   380 	return opt_verbosity;
   381 }
   383 void
   384 _tinytest_set_test_failed(void)
   385 {
   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;
   390 	}
   391 	cur_test_outcome = 0;
   392 }
   394 void
   395 _tinytest_set_test_skipped(void)
   396 {
   397 	if (cur_test_outcome==OK)
   398 		cur_test_outcome = SKIP;
   399 }

mercurial