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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/third_party/libevent/test/tinytest.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,400 @@
     1.4 +/* tinytest.c -- Copyright 2009-2012 Nick Mathewson
     1.5 + *
     1.6 + * Redistribution and use in source and binary forms, with or without
     1.7 + * modification, are permitted provided that the following conditions
     1.8 + * are met:
     1.9 + * 1. Redistributions of source code must retain the above copyright
    1.10 + *    notice, this list of conditions and the following disclaimer.
    1.11 + * 2. Redistributions in binary form must reproduce the above copyright
    1.12 + *    notice, this list of conditions and the following disclaimer in the
    1.13 + *    documentation and/or other materials provided with the distribution.
    1.14 + * 3. The name of the author may not be used to endorse or promote products
    1.15 + *    derived from this software without specific prior written permission.
    1.16 + *
    1.17 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    1.18 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    1.19 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    1.20 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    1.21 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    1.22 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.23 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.24 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.25 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    1.26 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.27 + */
    1.28 +
    1.29 +#include <stdio.h>
    1.30 +#include <stdlib.h>
    1.31 +#include <string.h>
    1.32 +#include <assert.h>
    1.33 +
    1.34 +#ifdef TINYTEST_LOCAL
    1.35 +#include "tinytest_local.h"
    1.36 +#endif
    1.37 +
    1.38 +#ifdef WIN32
    1.39 +#include <windows.h>
    1.40 +#else
    1.41 +#include <sys/types.h>
    1.42 +#include <sys/wait.h>
    1.43 +#include <unistd.h>
    1.44 +#endif
    1.45 +
    1.46 +#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
    1.47 +#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
    1.48 +    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
    1.49 +/* Workaround for a stupid bug in OSX 10.6 */
    1.50 +#define FORK_BREAKS_GCOV
    1.51 +#include <vproc.h>
    1.52 +#endif
    1.53 +#endif
    1.54 +
    1.55 +#ifndef __GNUC__
    1.56 +#define __attribute__(x)
    1.57 +#endif
    1.58 +
    1.59 +#include "tinytest.h"
    1.60 +#include "tinytest_macros.h"
    1.61 +
    1.62 +#define LONGEST_TEST_NAME 16384
    1.63 +
    1.64 +static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
    1.65 +static int n_ok = 0; /**< Number of tests that have passed */
    1.66 +static int n_bad = 0; /**< Number of tests that have failed. */
    1.67 +static int n_skipped = 0; /**< Number of tests that have been skipped. */
    1.68 +
    1.69 +static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/
    1.70 +static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
    1.71 +static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
    1.72 +const char *verbosity_flag = "";
    1.73 +
    1.74 +enum outcome { SKIP=2, OK=1, FAIL=0 };
    1.75 +static enum outcome cur_test_outcome = 0;
    1.76 +const char *cur_test_prefix = NULL; /**< prefix of the current test group */
    1.77 +/** Name of the current test, if we haven't logged is yet. Used for --quiet */
    1.78 +const char *cur_test_name = NULL;
    1.79 +
    1.80 +#ifdef WIN32
    1.81 +/* Copy of argv[0] for win32. */
    1.82 +static char commandname[MAX_PATH+1];
    1.83 +#endif
    1.84 +
    1.85 +static void usage(struct testgroup_t *groups, int list_groups)
    1.86 +  __attribute__((noreturn));
    1.87 +
    1.88 +static enum outcome
    1.89 +_testcase_run_bare(const struct testcase_t *testcase)
    1.90 +{
    1.91 +	void *env = NULL;
    1.92 +	int outcome;
    1.93 +	if (testcase->setup) {
    1.94 +		env = testcase->setup->setup_fn(testcase);
    1.95 +		if (!env)
    1.96 +			return FAIL;
    1.97 +		else if (env == (void*)TT_SKIP)
    1.98 +			return SKIP;
    1.99 +	}
   1.100 +
   1.101 +	cur_test_outcome = OK;
   1.102 +	testcase->fn(env);
   1.103 +	outcome = cur_test_outcome;
   1.104 +
   1.105 +	if (testcase->setup) {
   1.106 +		if (testcase->setup->cleanup_fn(testcase, env) == 0)
   1.107 +			outcome = FAIL;
   1.108 +	}
   1.109 +
   1.110 +	return outcome;
   1.111 +}
   1.112 +
   1.113 +#define MAGIC_EXITCODE 42
   1.114 +
   1.115 +static enum outcome
   1.116 +_testcase_run_forked(const struct testgroup_t *group,
   1.117 +		     const struct testcase_t *testcase)
   1.118 +{
   1.119 +#ifdef WIN32
   1.120 +	/* Fork? On Win32?  How primitive!  We'll do what the smart kids do:
   1.121 +	   we'll invoke our own exe (whose name we recall from the command
   1.122 +	   line) with a command line that tells it to run just the test we
   1.123 +	   want, and this time without forking.
   1.124 +
   1.125 +	   (No, threads aren't an option.  The whole point of forking is to
   1.126 +	   share no state between tests.)
   1.127 +	 */
   1.128 +	int ok;
   1.129 +	char buffer[LONGEST_TEST_NAME+256];
   1.130 +	STARTUPINFOA si;
   1.131 +	PROCESS_INFORMATION info;
   1.132 +	DWORD exitcode;
   1.133 +
   1.134 +	if (!in_tinytest_main) {
   1.135 +		printf("\nERROR.  On Windows, _testcase_run_forked must be"
   1.136 +		       " called from within tinytest_main.\n");
   1.137 +		abort();
   1.138 +	}
   1.139 +	if (opt_verbosity>0)
   1.140 +		printf("[forking] ");
   1.141 +
   1.142 +	snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
   1.143 +		 commandname, verbosity_flag, group->prefix, testcase->name);
   1.144 +
   1.145 +	memset(&si, 0, sizeof(si));
   1.146 +	memset(&info, 0, sizeof(info));
   1.147 +	si.cb = sizeof(si);
   1.148 +
   1.149 +	ok = CreateProcessA(commandname, buffer, NULL, NULL, 0,
   1.150 +			   0, NULL, NULL, &si, &info);
   1.151 +	if (!ok) {
   1.152 +		printf("CreateProcess failed!\n");
   1.153 +		return 0;
   1.154 +	}
   1.155 +	WaitForSingleObject(info.hProcess, INFINITE);
   1.156 +	GetExitCodeProcess(info.hProcess, &exitcode);
   1.157 +	CloseHandle(info.hProcess);
   1.158 +	CloseHandle(info.hThread);
   1.159 +	if (exitcode == 0)
   1.160 +		return OK;
   1.161 +	else if (exitcode == MAGIC_EXITCODE)
   1.162 +		return SKIP;
   1.163 +	else
   1.164 +		return FAIL;
   1.165 +#else
   1.166 +	int outcome_pipe[2];
   1.167 +	pid_t pid;
   1.168 +	(void)group;
   1.169 +
   1.170 +	if (pipe(outcome_pipe))
   1.171 +		perror("opening pipe");
   1.172 +
   1.173 +	if (opt_verbosity>0)
   1.174 +		printf("[forking] ");
   1.175 +	pid = fork();
   1.176 +#ifdef FORK_BREAKS_GCOV
   1.177 +	vproc_transaction_begin(0);
   1.178 +#endif
   1.179 +	if (!pid) {
   1.180 +		/* child. */
   1.181 +		int test_r, write_r;
   1.182 +		char b[1];
   1.183 +		close(outcome_pipe[0]);
   1.184 +		test_r = _testcase_run_bare(testcase);
   1.185 +		assert(0<=(int)test_r && (int)test_r<=2);
   1.186 +		b[0] = "NYS"[test_r];
   1.187 +		write_r = (int)write(outcome_pipe[1], b, 1);
   1.188 +		if (write_r != 1) {
   1.189 +			perror("write outcome to pipe");
   1.190 +			exit(1);
   1.191 +		}
   1.192 +		exit(0);
   1.193 +		return FAIL; /* unreachable */
   1.194 +	} else {
   1.195 +		/* parent */
   1.196 +		int status, r;
   1.197 +		char b[1];
   1.198 +		/* Close this now, so that if the other side closes it,
   1.199 +		 * our read fails. */
   1.200 +		close(outcome_pipe[1]);
   1.201 +		r = (int)read(outcome_pipe[0], b, 1);
   1.202 +		if (r == 0) {
   1.203 +			printf("[Lost connection!] ");
   1.204 +			return 0;
   1.205 +		} else if (r != 1) {
   1.206 +			perror("read outcome from pipe");
   1.207 +		}
   1.208 +		waitpid(pid, &status, 0);
   1.209 +		close(outcome_pipe[0]);
   1.210 +		return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
   1.211 +	}
   1.212 +#endif
   1.213 +}
   1.214 +
   1.215 +int
   1.216 +testcase_run_one(const struct testgroup_t *group,
   1.217 +		 const struct testcase_t *testcase)
   1.218 +{
   1.219 +	enum outcome outcome;
   1.220 +
   1.221 +	if (testcase->flags & TT_SKIP) {
   1.222 +		if (opt_verbosity>0)
   1.223 +			printf("%s%s: SKIPPED\n",
   1.224 +			    group->prefix, testcase->name);
   1.225 +		++n_skipped;
   1.226 +		return SKIP;
   1.227 +	}
   1.228 +
   1.229 +	if (opt_verbosity>0 && !opt_forked) {
   1.230 +		printf("%s%s: ", group->prefix, testcase->name);
   1.231 +	} else {
   1.232 +		if (opt_verbosity==0) printf(".");
   1.233 +		cur_test_prefix = group->prefix;
   1.234 +		cur_test_name = testcase->name;
   1.235 +	}
   1.236 +
   1.237 +	if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
   1.238 +		outcome = _testcase_run_forked(group, testcase);
   1.239 +	} else {
   1.240 +		outcome = _testcase_run_bare(testcase);
   1.241 +	}
   1.242 +
   1.243 +	if (outcome == OK) {
   1.244 +		++n_ok;
   1.245 +		if (opt_verbosity>0 && !opt_forked)
   1.246 +			puts(opt_verbosity==1?"OK":"");
   1.247 +	} else if (outcome == SKIP) {
   1.248 +		++n_skipped;
   1.249 +		if (opt_verbosity>0 && !opt_forked)
   1.250 +			puts("SKIPPED");
   1.251 +	} else {
   1.252 +		++n_bad;
   1.253 +		if (!opt_forked)
   1.254 +			printf("\n  [%s FAILED]\n", testcase->name);
   1.255 +	}
   1.256 +
   1.257 +	if (opt_forked) {
   1.258 +		exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
   1.259 +		return 1; /* unreachable */
   1.260 +	} else {
   1.261 +		return (int)outcome;
   1.262 +	}
   1.263 +}
   1.264 +
   1.265 +int
   1.266 +_tinytest_set_flag(struct testgroup_t *groups, const char *arg, unsigned long flag)
   1.267 +{
   1.268 +	int i, j;
   1.269 +	size_t length = LONGEST_TEST_NAME;
   1.270 +	char fullname[LONGEST_TEST_NAME];
   1.271 +	int found=0;
   1.272 +	if (strstr(arg, ".."))
   1.273 +		length = strstr(arg,"..")-arg;
   1.274 +	for (i=0; groups[i].prefix; ++i) {
   1.275 +		for (j=0; groups[i].cases[j].name; ++j) {
   1.276 +			snprintf(fullname, sizeof(fullname), "%s%s",
   1.277 +				 groups[i].prefix, groups[i].cases[j].name);
   1.278 +			if (!flag) /* Hack! */
   1.279 +				printf("    %s\n", fullname);
   1.280 +			if (!strncmp(fullname, arg, length)) {
   1.281 +				groups[i].cases[j].flags |= flag;
   1.282 +				++found;
   1.283 +			}
   1.284 +		}
   1.285 +	}
   1.286 +	return found;
   1.287 +}
   1.288 +
   1.289 +static void
   1.290 +usage(struct testgroup_t *groups, int list_groups)
   1.291 +{
   1.292 +	puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
   1.293 +	puts("  Specify tests by name, or using a prefix ending with '..'");
   1.294 +	puts("  To skip a test, list give its name prefixed with a colon.");
   1.295 +	puts("  Use --list-tests for a list of tests.");
   1.296 +	if (list_groups) {
   1.297 +		puts("Known tests are:");
   1.298 +		_tinytest_set_flag(groups, "..", 0);
   1.299 +	}
   1.300 +	exit(0);
   1.301 +}
   1.302 +
   1.303 +int
   1.304 +tinytest_main(int c, const char **v, struct testgroup_t *groups)
   1.305 +{
   1.306 +	int i, j, n=0;
   1.307 +
   1.308 +#ifdef WIN32
   1.309 +	const char *sp = strrchr(v[0], '.');
   1.310 +	const char *extension = "";
   1.311 +	if (!sp || stricmp(sp, ".exe"))
   1.312 +		extension = ".exe"; /* Add an exe so CreateProcess will work */
   1.313 +	snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension);
   1.314 +	commandname[MAX_PATH]='\0';
   1.315 +#endif
   1.316 +	for (i=1; i<c; ++i) {
   1.317 +		if (v[i][0] == '-') {
   1.318 +			if (!strcmp(v[i], "--RUNNING-FORKED")) {
   1.319 +				opt_forked = 1;
   1.320 +			} else if (!strcmp(v[i], "--no-fork")) {
   1.321 +				opt_nofork = 1;
   1.322 +			} else if (!strcmp(v[i], "--quiet")) {
   1.323 +				opt_verbosity = -1;
   1.324 +				verbosity_flag = "--quiet";
   1.325 +			} else if (!strcmp(v[i], "--verbose")) {
   1.326 +				opt_verbosity = 2;
   1.327 +				verbosity_flag = "--verbose";
   1.328 +			} else if (!strcmp(v[i], "--terse")) {
   1.329 +				opt_verbosity = 0;
   1.330 +				verbosity_flag = "--terse";
   1.331 +			} else if (!strcmp(v[i], "--help")) {
   1.332 +				usage(groups, 0);
   1.333 +			} else if (!strcmp(v[i], "--list-tests")) {
   1.334 +				usage(groups, 1);
   1.335 +			} else {
   1.336 +				printf("Unknown option %s.  Try --help\n",v[i]);
   1.337 +				return -1;
   1.338 +			}
   1.339 +		} else {
   1.340 +			const char *test = v[i];
   1.341 +			int flag = _TT_ENABLED;
   1.342 +			if (test[0] == ':') {
   1.343 +				++test;
   1.344 +				flag = TT_SKIP;
   1.345 +			} else {
   1.346 +				++n;
   1.347 +			}
   1.348 +			if (!_tinytest_set_flag(groups, test, flag)) {
   1.349 +				printf("No such test as %s!\n", v[i]);
   1.350 +				return -1;
   1.351 +			}
   1.352 +		}
   1.353 +	}
   1.354 +	if (!n)
   1.355 +		_tinytest_set_flag(groups, "..", _TT_ENABLED);
   1.356 +
   1.357 +	setvbuf(stdout, NULL, _IONBF, 0);
   1.358 +
   1.359 +	++in_tinytest_main;
   1.360 +	for (i=0; groups[i].prefix; ++i)
   1.361 +		for (j=0; groups[i].cases[j].name; ++j)
   1.362 +			if (groups[i].cases[j].flags & _TT_ENABLED)
   1.363 +				testcase_run_one(&groups[i],
   1.364 +						 &groups[i].cases[j]);
   1.365 +
   1.366 +	--in_tinytest_main;
   1.367 +
   1.368 +	if (opt_verbosity==0)
   1.369 +		puts("");
   1.370 +
   1.371 +	if (n_bad)
   1.372 +		printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad,
   1.373 +		       n_bad+n_ok,n_skipped);
   1.374 +	else if (opt_verbosity >= 1)
   1.375 +		printf("%d tests ok.  (%d skipped)\n", n_ok, n_skipped);
   1.376 +
   1.377 +	return (n_bad == 0) ? 0 : 1;
   1.378 +}
   1.379 +
   1.380 +int
   1.381 +_tinytest_get_verbosity(void)
   1.382 +{
   1.383 +	return opt_verbosity;
   1.384 +}
   1.385 +
   1.386 +void
   1.387 +_tinytest_set_test_failed(void)
   1.388 +{
   1.389 +	if (opt_verbosity <= 0 && cur_test_name) {
   1.390 +		if (opt_verbosity==0) puts("");
   1.391 +		printf("%s%s: ", cur_test_prefix, cur_test_name);
   1.392 +		cur_test_name = NULL;
   1.393 +	}
   1.394 +	cur_test_outcome = 0;
   1.395 +}
   1.396 +
   1.397 +void
   1.398 +_tinytest_set_test_skipped(void)
   1.399 +{
   1.400 +	if (cur_test_outcome==OK)
   1.401 +		cur_test_outcome = SKIP;
   1.402 +}
   1.403 +

mercurial