xref: /aosp_15_r20/external/libevent/test/tinytest.c (revision 663afb9b963571284e0f0a60f257164ab54f64bf)
1*663afb9bSAndroid Build Coastguard Worker /* tinytest.c -- Copyright 2009-2012 Nick Mathewson
2*663afb9bSAndroid Build Coastguard Worker  *
3*663afb9bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
4*663afb9bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
5*663afb9bSAndroid Build Coastguard Worker  * are met:
6*663afb9bSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
7*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
8*663afb9bSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
9*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
10*663afb9bSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
11*663afb9bSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
12*663afb9bSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
13*663afb9bSAndroid Build Coastguard Worker  *
14*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*663afb9bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*663afb9bSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*663afb9bSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18*663afb9bSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*663afb9bSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*663afb9bSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*663afb9bSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*663afb9bSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*663afb9bSAndroid Build Coastguard Worker  */
25*663afb9bSAndroid Build Coastguard Worker #ifdef TINYTEST_LOCAL
26*663afb9bSAndroid Build Coastguard Worker #include "tinytest_local.h"
27*663afb9bSAndroid Build Coastguard Worker #endif
28*663afb9bSAndroid Build Coastguard Worker 
29*663afb9bSAndroid Build Coastguard Worker #include <stdio.h>
30*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
31*663afb9bSAndroid Build Coastguard Worker #include <string.h>
32*663afb9bSAndroid Build Coastguard Worker #include <assert.h>
33*663afb9bSAndroid Build Coastguard Worker 
34*663afb9bSAndroid Build Coastguard Worker #ifndef NO_FORKING
35*663afb9bSAndroid Build Coastguard Worker 
36*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
37*663afb9bSAndroid Build Coastguard Worker #include <windows.h>
38*663afb9bSAndroid Build Coastguard Worker #else
39*663afb9bSAndroid Build Coastguard Worker #include <sys/types.h>
40*663afb9bSAndroid Build Coastguard Worker #include <sys/wait.h>
41*663afb9bSAndroid Build Coastguard Worker #include <unistd.h>
42*663afb9bSAndroid Build Coastguard Worker #endif
43*663afb9bSAndroid Build Coastguard Worker 
44*663afb9bSAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
45*663afb9bSAndroid Build Coastguard Worker #if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
46*663afb9bSAndroid Build Coastguard Worker     __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
47*663afb9bSAndroid Build Coastguard Worker /* Workaround for a stupid bug in OSX 10.6 */
48*663afb9bSAndroid Build Coastguard Worker #define FORK_BREAKS_GCOV
49*663afb9bSAndroid Build Coastguard Worker #include <vproc.h>
50*663afb9bSAndroid Build Coastguard Worker #endif
51*663afb9bSAndroid Build Coastguard Worker #endif
52*663afb9bSAndroid Build Coastguard Worker 
53*663afb9bSAndroid Build Coastguard Worker #endif /* !NO_FORKING */
54*663afb9bSAndroid Build Coastguard Worker 
55*663afb9bSAndroid Build Coastguard Worker #ifndef __GNUC__
56*663afb9bSAndroid Build Coastguard Worker #define __attribute__(x)
57*663afb9bSAndroid Build Coastguard Worker #endif
58*663afb9bSAndroid Build Coastguard Worker 
59*663afb9bSAndroid Build Coastguard Worker #include "tinytest.h"
60*663afb9bSAndroid Build Coastguard Worker #include "tinytest_macros.h"
61*663afb9bSAndroid Build Coastguard Worker 
62*663afb9bSAndroid Build Coastguard Worker #define LONGEST_TEST_NAME 16384
63*663afb9bSAndroid Build Coastguard Worker #define DEFAULT_TESTCASE_TIMEOUT 30U
64*663afb9bSAndroid Build Coastguard Worker #define MAGIC_EXITCODE 42
65*663afb9bSAndroid Build Coastguard Worker 
66*663afb9bSAndroid Build Coastguard Worker static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
67*663afb9bSAndroid Build Coastguard Worker static int n_ok = 0; /**< Number of tests that have passed */
68*663afb9bSAndroid Build Coastguard Worker static int n_bad = 0; /**< Number of tests that have failed. */
69*663afb9bSAndroid Build Coastguard Worker static int n_skipped = 0; /**< Number of tests that have been skipped. */
70*663afb9bSAndroid Build Coastguard Worker 
71*663afb9bSAndroid Build Coastguard Worker static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/
72*663afb9bSAndroid Build Coastguard Worker static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
73*663afb9bSAndroid Build Coastguard Worker static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
74*663afb9bSAndroid Build Coastguard Worker static unsigned int opt_timeout = DEFAULT_TESTCASE_TIMEOUT; /**< Timeout for every test (using alarm()) */
75*663afb9bSAndroid Build Coastguard Worker const char *verbosity_flag = "";
76*663afb9bSAndroid Build Coastguard Worker 
77*663afb9bSAndroid Build Coastguard Worker const struct testlist_alias_t *cfg_aliases=NULL;
78*663afb9bSAndroid Build Coastguard Worker 
79*663afb9bSAndroid Build Coastguard Worker enum outcome { SKIP=2, OK=1, FAIL=0 };
80*663afb9bSAndroid Build Coastguard Worker static enum outcome cur_test_outcome = 0;
81*663afb9bSAndroid Build Coastguard Worker const char *cur_test_prefix = NULL; /**< prefix of the current test group */
82*663afb9bSAndroid Build Coastguard Worker /** Name of the current test, if we haven't logged is yet. Used for --quiet */
83*663afb9bSAndroid Build Coastguard Worker const char *cur_test_name = NULL;
84*663afb9bSAndroid Build Coastguard Worker 
85*663afb9bSAndroid Build Coastguard Worker static void usage(struct testgroup_t *groups, int list_groups)
86*663afb9bSAndroid Build Coastguard Worker 	__attribute__((noreturn));
87*663afb9bSAndroid Build Coastguard Worker static int process_test_option(struct testgroup_t *groups, const char *test);
88*663afb9bSAndroid Build Coastguard Worker 
89*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
90*663afb9bSAndroid Build Coastguard Worker /* Copy of argv[0] for win32. */
91*663afb9bSAndroid Build Coastguard Worker static char commandname[MAX_PATH+1];
92*663afb9bSAndroid Build Coastguard Worker 
93*663afb9bSAndroid Build Coastguard Worker struct timeout_thread_args {
94*663afb9bSAndroid Build Coastguard Worker 	const testcase_fn *fn;
95*663afb9bSAndroid Build Coastguard Worker 	void *env;
96*663afb9bSAndroid Build Coastguard Worker };
97*663afb9bSAndroid Build Coastguard Worker 
98*663afb9bSAndroid Build Coastguard Worker static DWORD WINAPI
timeout_thread_proc_(LPVOID arg)99*663afb9bSAndroid Build Coastguard Worker timeout_thread_proc_(LPVOID arg)
100*663afb9bSAndroid Build Coastguard Worker {
101*663afb9bSAndroid Build Coastguard Worker 	struct timeout_thread_args *args = arg;
102*663afb9bSAndroid Build Coastguard Worker 	(*(args->fn))(args->env);
103*663afb9bSAndroid Build Coastguard Worker 	ExitThread(cur_test_outcome == FAIL ? 1 : 0);
104*663afb9bSAndroid Build Coastguard Worker }
105*663afb9bSAndroid Build Coastguard Worker 
106*663afb9bSAndroid Build Coastguard Worker static enum outcome
testcase_run_in_thread_(const struct testcase_t * testcase,void * env)107*663afb9bSAndroid Build Coastguard Worker testcase_run_in_thread_(const struct testcase_t *testcase, void *env)
108*663afb9bSAndroid Build Coastguard Worker {
109*663afb9bSAndroid Build Coastguard Worker 	/* We will never run testcase in a new thread when the
110*663afb9bSAndroid Build Coastguard Worker 	timeout is set to zero */
111*663afb9bSAndroid Build Coastguard Worker 	assert(opt_timeout);
112*663afb9bSAndroid Build Coastguard Worker 	DWORD ret, tid;
113*663afb9bSAndroid Build Coastguard Worker 	HANDLE handle;
114*663afb9bSAndroid Build Coastguard Worker 	struct timeout_thread_args args = {
115*663afb9bSAndroid Build Coastguard Worker 		&(testcase->fn),
116*663afb9bSAndroid Build Coastguard Worker 		env
117*663afb9bSAndroid Build Coastguard Worker 	};
118*663afb9bSAndroid Build Coastguard Worker 
119*663afb9bSAndroid Build Coastguard Worker 	handle =CreateThread(NULL, 0, timeout_thread_proc_,
120*663afb9bSAndroid Build Coastguard Worker 		(LPVOID)&args, 0, &tid);
121*663afb9bSAndroid Build Coastguard Worker 	ret = WaitForSingleObject(handle, opt_timeout * 1000U);
122*663afb9bSAndroid Build Coastguard Worker 	if (ret == WAIT_OBJECT_0) {
123*663afb9bSAndroid Build Coastguard Worker 		ret = 0;
124*663afb9bSAndroid Build Coastguard Worker 		if (!GetExitCodeThread(handle, &ret)) {
125*663afb9bSAndroid Build Coastguard Worker 			printf("GetExitCodeThread failed\n");
126*663afb9bSAndroid Build Coastguard Worker 			ret = 1;
127*663afb9bSAndroid Build Coastguard Worker 		}
128*663afb9bSAndroid Build Coastguard Worker 	} else if (ret == WAIT_TIMEOUT)	{
129*663afb9bSAndroid Build Coastguard Worker 		printf("timeout\n");
130*663afb9bSAndroid Build Coastguard Worker 	} else {
131*663afb9bSAndroid Build Coastguard Worker 		printf("Wait failed\n");
132*663afb9bSAndroid Build Coastguard Worker 	}
133*663afb9bSAndroid Build Coastguard Worker 	CloseHandle(handle);
134*663afb9bSAndroid Build Coastguard Worker 	if (ret == 0)
135*663afb9bSAndroid Build Coastguard Worker 		return OK;
136*663afb9bSAndroid Build Coastguard Worker 	else if (ret == MAGIC_EXITCODE)
137*663afb9bSAndroid Build Coastguard Worker 		return SKIP;
138*663afb9bSAndroid Build Coastguard Worker 	else
139*663afb9bSAndroid Build Coastguard Worker 		return FAIL;
140*663afb9bSAndroid Build Coastguard Worker }
141*663afb9bSAndroid Build Coastguard Worker #else
testcase_set_timeout_(void)142*663afb9bSAndroid Build Coastguard Worker static unsigned int testcase_set_timeout_(void)
143*663afb9bSAndroid Build Coastguard Worker {
144*663afb9bSAndroid Build Coastguard Worker 	return alarm(opt_timeout);
145*663afb9bSAndroid Build Coastguard Worker }
146*663afb9bSAndroid Build Coastguard Worker 
testcase_reset_timeout_(void)147*663afb9bSAndroid Build Coastguard Worker static unsigned int testcase_reset_timeout_(void)
148*663afb9bSAndroid Build Coastguard Worker {
149*663afb9bSAndroid Build Coastguard Worker 	return alarm(0);
150*663afb9bSAndroid Build Coastguard Worker }
151*663afb9bSAndroid Build Coastguard Worker #endif
152*663afb9bSAndroid Build Coastguard Worker 
153*663afb9bSAndroid Build Coastguard Worker static enum outcome
testcase_run_bare_(const struct testcase_t * testcase)154*663afb9bSAndroid Build Coastguard Worker testcase_run_bare_(const struct testcase_t *testcase)
155*663afb9bSAndroid Build Coastguard Worker {
156*663afb9bSAndroid Build Coastguard Worker 	void *env = NULL;
157*663afb9bSAndroid Build Coastguard Worker 	int outcome;
158*663afb9bSAndroid Build Coastguard Worker 	if (testcase->setup) {
159*663afb9bSAndroid Build Coastguard Worker 		env = testcase->setup->setup_fn(testcase);
160*663afb9bSAndroid Build Coastguard Worker 		if (!env)
161*663afb9bSAndroid Build Coastguard Worker 			return FAIL;
162*663afb9bSAndroid Build Coastguard Worker 		else if (env == (void*)TT_SKIP)
163*663afb9bSAndroid Build Coastguard Worker 			return SKIP;
164*663afb9bSAndroid Build Coastguard Worker 	}
165*663afb9bSAndroid Build Coastguard Worker 
166*663afb9bSAndroid Build Coastguard Worker 	cur_test_outcome = OK;
167*663afb9bSAndroid Build Coastguard Worker 	{
168*663afb9bSAndroid Build Coastguard Worker 		if (opt_timeout) {
169*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
170*663afb9bSAndroid Build Coastguard Worker 			cur_test_outcome = testcase_run_in_thread_(testcase, env);
171*663afb9bSAndroid Build Coastguard Worker #else
172*663afb9bSAndroid Build Coastguard Worker 			testcase_set_timeout_();
173*663afb9bSAndroid Build Coastguard Worker 			testcase->fn(env);
174*663afb9bSAndroid Build Coastguard Worker 			testcase_reset_timeout_();
175*663afb9bSAndroid Build Coastguard Worker #endif
176*663afb9bSAndroid Build Coastguard Worker 		} else {
177*663afb9bSAndroid Build Coastguard Worker 			testcase->fn(env);
178*663afb9bSAndroid Build Coastguard Worker 		}
179*663afb9bSAndroid Build Coastguard Worker 	}
180*663afb9bSAndroid Build Coastguard Worker 	outcome = cur_test_outcome;
181*663afb9bSAndroid Build Coastguard Worker 
182*663afb9bSAndroid Build Coastguard Worker 	if (testcase->setup) {
183*663afb9bSAndroid Build Coastguard Worker 		if (testcase->setup->cleanup_fn(testcase, env) == 0)
184*663afb9bSAndroid Build Coastguard Worker 			outcome = FAIL;
185*663afb9bSAndroid Build Coastguard Worker 	}
186*663afb9bSAndroid Build Coastguard Worker 
187*663afb9bSAndroid Build Coastguard Worker 	return outcome;
188*663afb9bSAndroid Build Coastguard Worker }
189*663afb9bSAndroid Build Coastguard Worker 
190*663afb9bSAndroid Build Coastguard Worker 
191*663afb9bSAndroid Build Coastguard Worker #ifndef NO_FORKING
192*663afb9bSAndroid Build Coastguard Worker 
193*663afb9bSAndroid Build Coastguard Worker static enum outcome
testcase_run_forked_(const struct testgroup_t * group,const struct testcase_t * testcase)194*663afb9bSAndroid Build Coastguard Worker testcase_run_forked_(const struct testgroup_t *group,
195*663afb9bSAndroid Build Coastguard Worker 		     const struct testcase_t *testcase)
196*663afb9bSAndroid Build Coastguard Worker {
197*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
198*663afb9bSAndroid Build Coastguard Worker 	/* Fork? On Win32?  How primitive!  We'll do what the smart kids do:
199*663afb9bSAndroid Build Coastguard Worker 	   we'll invoke our own exe (whose name we recall from the command
200*663afb9bSAndroid Build Coastguard Worker 	   line) with a command line that tells it to run just the test we
201*663afb9bSAndroid Build Coastguard Worker 	   want, and this time without forking.
202*663afb9bSAndroid Build Coastguard Worker 
203*663afb9bSAndroid Build Coastguard Worker 	   (No, threads aren't an option.  The whole point of forking is to
204*663afb9bSAndroid Build Coastguard Worker 	   share no state between tests.)
205*663afb9bSAndroid Build Coastguard Worker 	 */
206*663afb9bSAndroid Build Coastguard Worker 	int ok;
207*663afb9bSAndroid Build Coastguard Worker 	char buffer[LONGEST_TEST_NAME+256];
208*663afb9bSAndroid Build Coastguard Worker 	STARTUPINFOA si;
209*663afb9bSAndroid Build Coastguard Worker 	PROCESS_INFORMATION info;
210*663afb9bSAndroid Build Coastguard Worker 	DWORD ret;
211*663afb9bSAndroid Build Coastguard Worker 
212*663afb9bSAndroid Build Coastguard Worker 	if (!in_tinytest_main) {
213*663afb9bSAndroid Build Coastguard Worker 		printf("\nERROR.  On Windows, testcase_run_forked_ must be"
214*663afb9bSAndroid Build Coastguard Worker 		       " called from within tinytest_main.\n");
215*663afb9bSAndroid Build Coastguard Worker 		abort();
216*663afb9bSAndroid Build Coastguard Worker 	}
217*663afb9bSAndroid Build Coastguard Worker 	if (opt_verbosity>0)
218*663afb9bSAndroid Build Coastguard Worker 		printf("[forking] ");
219*663afb9bSAndroid Build Coastguard Worker 
220*663afb9bSAndroid Build Coastguard Worker 	snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s --timeout 0 %s%s",
221*663afb9bSAndroid Build Coastguard Worker 		 commandname, verbosity_flag, group->prefix, testcase->name);
222*663afb9bSAndroid Build Coastguard Worker 
223*663afb9bSAndroid Build Coastguard Worker 	memset(&si, 0, sizeof(si));
224*663afb9bSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof(info));
225*663afb9bSAndroid Build Coastguard Worker 	si.cb = sizeof(si);
226*663afb9bSAndroid Build Coastguard Worker 
227*663afb9bSAndroid Build Coastguard Worker 	ok = CreateProcessA(commandname, buffer, NULL, NULL, 0,
228*663afb9bSAndroid Build Coastguard Worker 			   0, NULL, NULL, &si, &info);
229*663afb9bSAndroid Build Coastguard Worker 	if (!ok) {
230*663afb9bSAndroid Build Coastguard Worker 		printf("CreateProcess failed!\n");
231*663afb9bSAndroid Build Coastguard Worker 		return FAIL;
232*663afb9bSAndroid Build Coastguard Worker 	}
233*663afb9bSAndroid Build Coastguard Worker 	ret = WaitForSingleObject(info.hProcess,
234*663afb9bSAndroid Build Coastguard Worker 		(opt_timeout ? opt_timeout * 1000U : INFINITE));
235*663afb9bSAndroid Build Coastguard Worker 
236*663afb9bSAndroid Build Coastguard Worker 	if (ret == WAIT_OBJECT_0) {
237*663afb9bSAndroid Build Coastguard Worker 		GetExitCodeProcess(info.hProcess, &ret);
238*663afb9bSAndroid Build Coastguard Worker 	} else if (ret == WAIT_TIMEOUT) {
239*663afb9bSAndroid Build Coastguard Worker 		printf("timeout\n");
240*663afb9bSAndroid Build Coastguard Worker 	} else {
241*663afb9bSAndroid Build Coastguard Worker 		printf("Wait failed\n");
242*663afb9bSAndroid Build Coastguard Worker 	}
243*663afb9bSAndroid Build Coastguard Worker 	CloseHandle(info.hProcess);
244*663afb9bSAndroid Build Coastguard Worker 	CloseHandle(info.hThread);
245*663afb9bSAndroid Build Coastguard Worker 	if (ret == 0)
246*663afb9bSAndroid Build Coastguard Worker 		return OK;
247*663afb9bSAndroid Build Coastguard Worker 	else if (ret == MAGIC_EXITCODE)
248*663afb9bSAndroid Build Coastguard Worker 		return SKIP;
249*663afb9bSAndroid Build Coastguard Worker 	else
250*663afb9bSAndroid Build Coastguard Worker 		return FAIL;
251*663afb9bSAndroid Build Coastguard Worker #else
252*663afb9bSAndroid Build Coastguard Worker 	int outcome_pipe[2];
253*663afb9bSAndroid Build Coastguard Worker 	pid_t pid;
254*663afb9bSAndroid Build Coastguard Worker 	(void)group;
255*663afb9bSAndroid Build Coastguard Worker 
256*663afb9bSAndroid Build Coastguard Worker 	if (pipe(outcome_pipe))
257*663afb9bSAndroid Build Coastguard Worker 		perror("opening pipe");
258*663afb9bSAndroid Build Coastguard Worker 
259*663afb9bSAndroid Build Coastguard Worker 	if (opt_verbosity>0)
260*663afb9bSAndroid Build Coastguard Worker 		printf("[forking] ");
261*663afb9bSAndroid Build Coastguard Worker 	pid = fork();
262*663afb9bSAndroid Build Coastguard Worker #ifdef FORK_BREAKS_GCOV
263*663afb9bSAndroid Build Coastguard Worker 	vproc_transaction_begin(0);
264*663afb9bSAndroid Build Coastguard Worker #endif
265*663afb9bSAndroid Build Coastguard Worker 	if (!pid) {
266*663afb9bSAndroid Build Coastguard Worker 		/* child. */
267*663afb9bSAndroid Build Coastguard Worker 		int test_r, write_r;
268*663afb9bSAndroid Build Coastguard Worker 		char b[1];
269*663afb9bSAndroid Build Coastguard Worker 		close(outcome_pipe[0]);
270*663afb9bSAndroid Build Coastguard Worker 		test_r = testcase_run_bare_(testcase);
271*663afb9bSAndroid Build Coastguard Worker 		assert(0<=(int)test_r && (int)test_r<=2);
272*663afb9bSAndroid Build Coastguard Worker 		b[0] = "NYS"[test_r];
273*663afb9bSAndroid Build Coastguard Worker 		write_r = (int)write(outcome_pipe[1], b, 1);
274*663afb9bSAndroid Build Coastguard Worker 		if (write_r != 1) {
275*663afb9bSAndroid Build Coastguard Worker 			perror("write outcome to pipe");
276*663afb9bSAndroid Build Coastguard Worker 			exit(1);
277*663afb9bSAndroid Build Coastguard Worker 		}
278*663afb9bSAndroid Build Coastguard Worker 		exit(0);
279*663afb9bSAndroid Build Coastguard Worker 		return FAIL; /* unreachable */
280*663afb9bSAndroid Build Coastguard Worker 	} else {
281*663afb9bSAndroid Build Coastguard Worker 		/* parent */
282*663afb9bSAndroid Build Coastguard Worker 		int status, r, exitcode;
283*663afb9bSAndroid Build Coastguard Worker 		char b[1];
284*663afb9bSAndroid Build Coastguard Worker 		/* Close this now, so that if the other side closes it,
285*663afb9bSAndroid Build Coastguard Worker 		 * our read fails. */
286*663afb9bSAndroid Build Coastguard Worker 		close(outcome_pipe[1]);
287*663afb9bSAndroid Build Coastguard Worker 		r = (int)read(outcome_pipe[0], b, 1);
288*663afb9bSAndroid Build Coastguard Worker 		if (r == 0) {
289*663afb9bSAndroid Build Coastguard Worker 			printf("[Lost connection!] ");
290*663afb9bSAndroid Build Coastguard Worker 			return FAIL;
291*663afb9bSAndroid Build Coastguard Worker 		} else if (r != 1) {
292*663afb9bSAndroid Build Coastguard Worker 			perror("read outcome from pipe");
293*663afb9bSAndroid Build Coastguard Worker 		}
294*663afb9bSAndroid Build Coastguard Worker 		waitpid(pid, &status, 0);
295*663afb9bSAndroid Build Coastguard Worker 		exitcode = WEXITSTATUS(status);
296*663afb9bSAndroid Build Coastguard Worker 		close(outcome_pipe[0]);
297*663afb9bSAndroid Build Coastguard Worker 		if (opt_verbosity>1)
298*663afb9bSAndroid Build Coastguard Worker 			printf("%s%s: exited with %i (%i)\n", group->prefix, testcase->name, exitcode, status);
299*663afb9bSAndroid Build Coastguard Worker 		if (exitcode != 0)
300*663afb9bSAndroid Build Coastguard Worker 		{
301*663afb9bSAndroid Build Coastguard Worker 			printf("[atexit failure!] ");
302*663afb9bSAndroid Build Coastguard Worker 			return FAIL;
303*663afb9bSAndroid Build Coastguard Worker 		}
304*663afb9bSAndroid Build Coastguard Worker 		return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
305*663afb9bSAndroid Build Coastguard Worker 	}
306*663afb9bSAndroid Build Coastguard Worker #endif
307*663afb9bSAndroid Build Coastguard Worker }
308*663afb9bSAndroid Build Coastguard Worker 
309*663afb9bSAndroid Build Coastguard Worker #endif /* !NO_FORKING */
310*663afb9bSAndroid Build Coastguard Worker 
311*663afb9bSAndroid Build Coastguard Worker int
testcase_run_one(const struct testgroup_t * group,const struct testcase_t * testcase)312*663afb9bSAndroid Build Coastguard Worker testcase_run_one(const struct testgroup_t *group,
313*663afb9bSAndroid Build Coastguard Worker 		 const struct testcase_t *testcase)
314*663afb9bSAndroid Build Coastguard Worker {
315*663afb9bSAndroid Build Coastguard Worker 	enum outcome outcome;
316*663afb9bSAndroid Build Coastguard Worker 
317*663afb9bSAndroid Build Coastguard Worker 	if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) {
318*663afb9bSAndroid Build Coastguard Worker 		if (opt_verbosity>0)
319*663afb9bSAndroid Build Coastguard Worker 			printf("%s%s: %s\n",
320*663afb9bSAndroid Build Coastguard Worker 			   group->prefix, testcase->name,
321*663afb9bSAndroid Build Coastguard Worker 			   (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED");
322*663afb9bSAndroid Build Coastguard Worker 		++n_skipped;
323*663afb9bSAndroid Build Coastguard Worker 		return SKIP;
324*663afb9bSAndroid Build Coastguard Worker 	}
325*663afb9bSAndroid Build Coastguard Worker 
326*663afb9bSAndroid Build Coastguard Worker 	if (opt_verbosity>0 && !opt_forked) {
327*663afb9bSAndroid Build Coastguard Worker 		printf("%s%s: ", group->prefix, testcase->name);
328*663afb9bSAndroid Build Coastguard Worker 	} else {
329*663afb9bSAndroid Build Coastguard Worker 		if (opt_verbosity==0) printf(".");
330*663afb9bSAndroid Build Coastguard Worker 		cur_test_prefix = group->prefix;
331*663afb9bSAndroid Build Coastguard Worker 		cur_test_name = testcase->name;
332*663afb9bSAndroid Build Coastguard Worker 	}
333*663afb9bSAndroid Build Coastguard Worker 
334*663afb9bSAndroid Build Coastguard Worker #ifndef NO_FORKING
335*663afb9bSAndroid Build Coastguard Worker 	if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
336*663afb9bSAndroid Build Coastguard Worker 		outcome = testcase_run_forked_(group, testcase);
337*663afb9bSAndroid Build Coastguard Worker 	} else {
338*663afb9bSAndroid Build Coastguard Worker #else
339*663afb9bSAndroid Build Coastguard Worker 	{
340*663afb9bSAndroid Build Coastguard Worker #endif
341*663afb9bSAndroid Build Coastguard Worker 		outcome = testcase_run_bare_(testcase);
342*663afb9bSAndroid Build Coastguard Worker 	}
343*663afb9bSAndroid Build Coastguard Worker 
344*663afb9bSAndroid Build Coastguard Worker 	if (outcome == OK) {
345*663afb9bSAndroid Build Coastguard Worker 		if (opt_verbosity>0 && !opt_forked)
346*663afb9bSAndroid Build Coastguard Worker 			puts(opt_verbosity==1?"OK":"");
347*663afb9bSAndroid Build Coastguard Worker 	} else if (outcome == SKIP) {
348*663afb9bSAndroid Build Coastguard Worker 		if (opt_verbosity>0 && !opt_forked)
349*663afb9bSAndroid Build Coastguard Worker 			puts("SKIPPED");
350*663afb9bSAndroid Build Coastguard Worker 	} else {
351*663afb9bSAndroid Build Coastguard Worker 		if (!opt_forked)
352*663afb9bSAndroid Build Coastguard Worker 			printf("\n  [%s FAILED]\n", testcase->name);
353*663afb9bSAndroid Build Coastguard Worker 	}
354*663afb9bSAndroid Build Coastguard Worker 
355*663afb9bSAndroid Build Coastguard Worker 	if (opt_forked) {
356*663afb9bSAndroid Build Coastguard Worker 		exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
357*663afb9bSAndroid Build Coastguard Worker 		return 1; /* unreachable */
358*663afb9bSAndroid Build Coastguard Worker 	} else {
359*663afb9bSAndroid Build Coastguard Worker 		return (int)outcome;
360*663afb9bSAndroid Build Coastguard Worker 	}
361*663afb9bSAndroid Build Coastguard Worker }
362*663afb9bSAndroid Build Coastguard Worker 
363*663afb9bSAndroid Build Coastguard Worker int
364*663afb9bSAndroid Build Coastguard Worker tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag)
365*663afb9bSAndroid Build Coastguard Worker {
366*663afb9bSAndroid Build Coastguard Worker 	int i, j;
367*663afb9bSAndroid Build Coastguard Worker 	size_t length = LONGEST_TEST_NAME;
368*663afb9bSAndroid Build Coastguard Worker 	char fullname[LONGEST_TEST_NAME];
369*663afb9bSAndroid Build Coastguard Worker 	int found=0;
370*663afb9bSAndroid Build Coastguard Worker 	if (strstr(arg, ".."))
371*663afb9bSAndroid Build Coastguard Worker 		length = strstr(arg,"..")-arg;
372*663afb9bSAndroid Build Coastguard Worker 	for (i=0; groups[i].prefix; ++i) {
373*663afb9bSAndroid Build Coastguard Worker 		for (j=0; groups[i].cases[j].name; ++j) {
374*663afb9bSAndroid Build Coastguard Worker 			struct testcase_t *testcase = &groups[i].cases[j];
375*663afb9bSAndroid Build Coastguard Worker 			snprintf(fullname, sizeof(fullname), "%s%s",
376*663afb9bSAndroid Build Coastguard Worker 				 groups[i].prefix, testcase->name);
377*663afb9bSAndroid Build Coastguard Worker 			if (!flag) { /* Hack! */
378*663afb9bSAndroid Build Coastguard Worker 				printf("    %s", fullname);
379*663afb9bSAndroid Build Coastguard Worker 				if (testcase->flags & TT_OFF_BY_DEFAULT)
380*663afb9bSAndroid Build Coastguard Worker 					puts("   (Off by default)");
381*663afb9bSAndroid Build Coastguard Worker 				else if (testcase->flags & TT_SKIP)
382*663afb9bSAndroid Build Coastguard Worker 					puts("  (DISABLED)");
383*663afb9bSAndroid Build Coastguard Worker 				else
384*663afb9bSAndroid Build Coastguard Worker 					puts("");
385*663afb9bSAndroid Build Coastguard Worker 			}
386*663afb9bSAndroid Build Coastguard Worker 			if (!strncmp(fullname, arg, length)) {
387*663afb9bSAndroid Build Coastguard Worker 				if (set)
388*663afb9bSAndroid Build Coastguard Worker 					testcase->flags |= flag;
389*663afb9bSAndroid Build Coastguard Worker 				else
390*663afb9bSAndroid Build Coastguard Worker 					testcase->flags &= ~flag;
391*663afb9bSAndroid Build Coastguard Worker 				++found;
392*663afb9bSAndroid Build Coastguard Worker 			}
393*663afb9bSAndroid Build Coastguard Worker 		}
394*663afb9bSAndroid Build Coastguard Worker 	}
395*663afb9bSAndroid Build Coastguard Worker 	return found;
396*663afb9bSAndroid Build Coastguard Worker }
397*663afb9bSAndroid Build Coastguard Worker 
398*663afb9bSAndroid Build Coastguard Worker static void
399*663afb9bSAndroid Build Coastguard Worker usage(struct testgroup_t *groups, int list_groups)
400*663afb9bSAndroid Build Coastguard Worker {
401*663afb9bSAndroid Build Coastguard Worker 	puts("Options are: [--verbose|--quiet|--terse] [--no-fork] [--timeout <sec>]");
402*663afb9bSAndroid Build Coastguard Worker 	puts("  Specify tests by name, or using a prefix ending with '..'");
403*663afb9bSAndroid Build Coastguard Worker 	puts("  To skip a test, prefix its name with a colon.");
404*663afb9bSAndroid Build Coastguard Worker 	puts("  To enable a disabled test, prefix its name with a plus.");
405*663afb9bSAndroid Build Coastguard Worker 	puts("  Use --list-tests for a list of tests.");
406*663afb9bSAndroid Build Coastguard Worker 	if (list_groups) {
407*663afb9bSAndroid Build Coastguard Worker 		puts("Known tests are:");
408*663afb9bSAndroid Build Coastguard Worker 		tinytest_set_flag_(groups, "..", 1, 0);
409*663afb9bSAndroid Build Coastguard Worker 	}
410*663afb9bSAndroid Build Coastguard Worker 	exit(0);
411*663afb9bSAndroid Build Coastguard Worker }
412*663afb9bSAndroid Build Coastguard Worker 
413*663afb9bSAndroid Build Coastguard Worker static int
414*663afb9bSAndroid Build Coastguard Worker process_test_alias(struct testgroup_t *groups, const char *test)
415*663afb9bSAndroid Build Coastguard Worker {
416*663afb9bSAndroid Build Coastguard Worker 	int i, j, n, r;
417*663afb9bSAndroid Build Coastguard Worker 	for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) {
418*663afb9bSAndroid Build Coastguard Worker 		if (!strcmp(cfg_aliases[i].name, test)) {
419*663afb9bSAndroid Build Coastguard Worker 			n = 0;
420*663afb9bSAndroid Build Coastguard Worker 			for (j = 0; cfg_aliases[i].tests[j]; ++j) {
421*663afb9bSAndroid Build Coastguard Worker 				r = process_test_option(groups, cfg_aliases[i].tests[j]);
422*663afb9bSAndroid Build Coastguard Worker 				if (r<0)
423*663afb9bSAndroid Build Coastguard Worker 					return -1;
424*663afb9bSAndroid Build Coastguard Worker 				n += r;
425*663afb9bSAndroid Build Coastguard Worker 			}
426*663afb9bSAndroid Build Coastguard Worker 			return n;
427*663afb9bSAndroid Build Coastguard Worker 		}
428*663afb9bSAndroid Build Coastguard Worker 	}
429*663afb9bSAndroid Build Coastguard Worker 	printf("No such test alias as @%s!",test);
430*663afb9bSAndroid Build Coastguard Worker 	return -1;
431*663afb9bSAndroid Build Coastguard Worker }
432*663afb9bSAndroid Build Coastguard Worker 
433*663afb9bSAndroid Build Coastguard Worker static int
434*663afb9bSAndroid Build Coastguard Worker process_test_option(struct testgroup_t *groups, const char *test)
435*663afb9bSAndroid Build Coastguard Worker {
436*663afb9bSAndroid Build Coastguard Worker 	int flag = TT_ENABLED_;
437*663afb9bSAndroid Build Coastguard Worker 	int n = 0;
438*663afb9bSAndroid Build Coastguard Worker 	if (test[0] == '@') {
439*663afb9bSAndroid Build Coastguard Worker 		return process_test_alias(groups, test + 1);
440*663afb9bSAndroid Build Coastguard Worker 	} else if (test[0] == ':') {
441*663afb9bSAndroid Build Coastguard Worker 		++test;
442*663afb9bSAndroid Build Coastguard Worker 		flag = TT_SKIP;
443*663afb9bSAndroid Build Coastguard Worker 	} else if (test[0] == '+') {
444*663afb9bSAndroid Build Coastguard Worker 		++test;
445*663afb9bSAndroid Build Coastguard Worker 		++n;
446*663afb9bSAndroid Build Coastguard Worker 		if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) {
447*663afb9bSAndroid Build Coastguard Worker 			printf("No such test as %s!\n", test);
448*663afb9bSAndroid Build Coastguard Worker 			return -1;
449*663afb9bSAndroid Build Coastguard Worker 		}
450*663afb9bSAndroid Build Coastguard Worker 	} else {
451*663afb9bSAndroid Build Coastguard Worker 		++n;
452*663afb9bSAndroid Build Coastguard Worker 	}
453*663afb9bSAndroid Build Coastguard Worker 	if (!tinytest_set_flag_(groups, test, 1, flag)) {
454*663afb9bSAndroid Build Coastguard Worker 		printf("No such test as %s!\n", test);
455*663afb9bSAndroid Build Coastguard Worker 		return -1;
456*663afb9bSAndroid Build Coastguard Worker 	}
457*663afb9bSAndroid Build Coastguard Worker 	return n;
458*663afb9bSAndroid Build Coastguard Worker }
459*663afb9bSAndroid Build Coastguard Worker 
460*663afb9bSAndroid Build Coastguard Worker void
461*663afb9bSAndroid Build Coastguard Worker tinytest_set_aliases(const struct testlist_alias_t *aliases)
462*663afb9bSAndroid Build Coastguard Worker {
463*663afb9bSAndroid Build Coastguard Worker 	cfg_aliases = aliases;
464*663afb9bSAndroid Build Coastguard Worker }
465*663afb9bSAndroid Build Coastguard Worker 
466*663afb9bSAndroid Build Coastguard Worker int
467*663afb9bSAndroid Build Coastguard Worker tinytest_main(int c, const char **v, struct testgroup_t *groups)
468*663afb9bSAndroid Build Coastguard Worker {
469*663afb9bSAndroid Build Coastguard Worker 	int i, j, n=0;
470*663afb9bSAndroid Build Coastguard Worker 
471*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
472*663afb9bSAndroid Build Coastguard Worker 	const char *sp = strrchr(v[0], '.');
473*663afb9bSAndroid Build Coastguard Worker 	const char *extension = "";
474*663afb9bSAndroid Build Coastguard Worker 	if (!sp || stricmp(sp, ".exe"))
475*663afb9bSAndroid Build Coastguard Worker 		extension = ".exe"; /* Add an exe so CreateProcess will work */
476*663afb9bSAndroid Build Coastguard Worker 	snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension);
477*663afb9bSAndroid Build Coastguard Worker 	commandname[MAX_PATH]='\0';
478*663afb9bSAndroid Build Coastguard Worker #endif
479*663afb9bSAndroid Build Coastguard Worker 	for (i=1; i<c; ++i) {
480*663afb9bSAndroid Build Coastguard Worker 		if (v[i][0] == '-') {
481*663afb9bSAndroid Build Coastguard Worker 			if (!strcmp(v[i], "--RUNNING-FORKED")) {
482*663afb9bSAndroid Build Coastguard Worker 				opt_forked = 1;
483*663afb9bSAndroid Build Coastguard Worker 			} else if (!strcmp(v[i], "--no-fork")) {
484*663afb9bSAndroid Build Coastguard Worker 				opt_nofork = 1;
485*663afb9bSAndroid Build Coastguard Worker 			} else if (!strcmp(v[i], "--quiet")) {
486*663afb9bSAndroid Build Coastguard Worker 				opt_verbosity = -1;
487*663afb9bSAndroid Build Coastguard Worker 				verbosity_flag = "--quiet";
488*663afb9bSAndroid Build Coastguard Worker 			} else if (!strcmp(v[i], "--verbose")) {
489*663afb9bSAndroid Build Coastguard Worker 				opt_verbosity = 2;
490*663afb9bSAndroid Build Coastguard Worker 				verbosity_flag = "--verbose";
491*663afb9bSAndroid Build Coastguard Worker 			} else if (!strcmp(v[i], "--terse")) {
492*663afb9bSAndroid Build Coastguard Worker 				opt_verbosity = 0;
493*663afb9bSAndroid Build Coastguard Worker 				verbosity_flag = "--terse";
494*663afb9bSAndroid Build Coastguard Worker 			} else if (!strcmp(v[i], "--help")) {
495*663afb9bSAndroid Build Coastguard Worker 				usage(groups, 0);
496*663afb9bSAndroid Build Coastguard Worker 			} else if (!strcmp(v[i], "--list-tests")) {
497*663afb9bSAndroid Build Coastguard Worker 				usage(groups, 1);
498*663afb9bSAndroid Build Coastguard Worker 			} else if (!strcmp(v[i], "--timeout")) {
499*663afb9bSAndroid Build Coastguard Worker 				++i;
500*663afb9bSAndroid Build Coastguard Worker 				if (i >= c) {
501*663afb9bSAndroid Build Coastguard Worker 					fprintf(stderr, "--timeout requires argument\n");
502*663afb9bSAndroid Build Coastguard Worker 					return -1;
503*663afb9bSAndroid Build Coastguard Worker 				}
504*663afb9bSAndroid Build Coastguard Worker 				opt_timeout = (unsigned)atoi(v[i]);
505*663afb9bSAndroid Build Coastguard Worker 			} else {
506*663afb9bSAndroid Build Coastguard Worker 				fprintf(stderr, "Unknown option %s. Try --help\n", v[i]);
507*663afb9bSAndroid Build Coastguard Worker 				return -1;
508*663afb9bSAndroid Build Coastguard Worker 			}
509*663afb9bSAndroid Build Coastguard Worker 		} else {
510*663afb9bSAndroid Build Coastguard Worker 			int r = process_test_option(groups, v[i]);
511*663afb9bSAndroid Build Coastguard Worker 			if (r<0)
512*663afb9bSAndroid Build Coastguard Worker 				return -1;
513*663afb9bSAndroid Build Coastguard Worker 			n += r;
514*663afb9bSAndroid Build Coastguard Worker 		}
515*663afb9bSAndroid Build Coastguard Worker 	}
516*663afb9bSAndroid Build Coastguard Worker 	if (!n)
517*663afb9bSAndroid Build Coastguard Worker 		tinytest_set_flag_(groups, "..", 1, TT_ENABLED_);
518*663afb9bSAndroid Build Coastguard Worker 
519*663afb9bSAndroid Build Coastguard Worker #ifdef _IONBF
520*663afb9bSAndroid Build Coastguard Worker 	setvbuf(stdout, NULL, _IONBF, 0);
521*663afb9bSAndroid Build Coastguard Worker #endif
522*663afb9bSAndroid Build Coastguard Worker 
523*663afb9bSAndroid Build Coastguard Worker 	++in_tinytest_main;
524*663afb9bSAndroid Build Coastguard Worker 	for (i = 0; groups[i].prefix; ++i) {
525*663afb9bSAndroid Build Coastguard Worker 		struct testgroup_t *group = &groups[i];
526*663afb9bSAndroid Build Coastguard Worker 		for (j = 0; group->cases[j].name; ++j) {
527*663afb9bSAndroid Build Coastguard Worker 			struct testcase_t *testcase = &group->cases[j];
528*663afb9bSAndroid Build Coastguard Worker 			int test_attempts = 3;
529*663afb9bSAndroid Build Coastguard Worker 			int test_ret_err;
530*663afb9bSAndroid Build Coastguard Worker 
531*663afb9bSAndroid Build Coastguard Worker 			if (!(testcase->flags & TT_ENABLED_))
532*663afb9bSAndroid Build Coastguard Worker 				continue;
533*663afb9bSAndroid Build Coastguard Worker 
534*663afb9bSAndroid Build Coastguard Worker 			for (;;) {
535*663afb9bSAndroid Build Coastguard Worker 				test_ret_err = testcase_run_one(group, testcase);
536*663afb9bSAndroid Build Coastguard Worker 
537*663afb9bSAndroid Build Coastguard Worker 				if (test_ret_err == OK)
538*663afb9bSAndroid Build Coastguard Worker 					break;
539*663afb9bSAndroid Build Coastguard Worker 				if (!(testcase->flags & TT_RETRIABLE))
540*663afb9bSAndroid Build Coastguard Worker 					break;
541*663afb9bSAndroid Build Coastguard Worker 				printf("\n  [RETRYING %s (%i)]\n", testcase->name, test_attempts);
542*663afb9bSAndroid Build Coastguard Worker 				if (!test_attempts--)
543*663afb9bSAndroid Build Coastguard Worker 					break;
544*663afb9bSAndroid Build Coastguard Worker 			}
545*663afb9bSAndroid Build Coastguard Worker 
546*663afb9bSAndroid Build Coastguard Worker 			switch (test_ret_err) {
547*663afb9bSAndroid Build Coastguard Worker 				case OK:   ++n_ok;      break;
548*663afb9bSAndroid Build Coastguard Worker 				case SKIP: ++n_skipped; break;
549*663afb9bSAndroid Build Coastguard Worker 				default:   ++n_bad;     break;
550*663afb9bSAndroid Build Coastguard Worker 			}
551*663afb9bSAndroid Build Coastguard Worker 		}
552*663afb9bSAndroid Build Coastguard Worker 	}
553*663afb9bSAndroid Build Coastguard Worker 
554*663afb9bSAndroid Build Coastguard Worker 	--in_tinytest_main;
555*663afb9bSAndroid Build Coastguard Worker 
556*663afb9bSAndroid Build Coastguard Worker 	if (opt_verbosity==0)
557*663afb9bSAndroid Build Coastguard Worker 		puts("");
558*663afb9bSAndroid Build Coastguard Worker 
559*663afb9bSAndroid Build Coastguard Worker 	if (n_bad)
560*663afb9bSAndroid Build Coastguard Worker 		printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad,
561*663afb9bSAndroid Build Coastguard Worker 		       n_bad+n_ok,n_skipped);
562*663afb9bSAndroid Build Coastguard Worker 	else if (opt_verbosity >= 1)
563*663afb9bSAndroid Build Coastguard Worker 		printf("%d tests ok.  (%d skipped)\n", n_ok, n_skipped);
564*663afb9bSAndroid Build Coastguard Worker 
565*663afb9bSAndroid Build Coastguard Worker 	return (n_bad == 0) ? 0 : 1;
566*663afb9bSAndroid Build Coastguard Worker }
567*663afb9bSAndroid Build Coastguard Worker 
568*663afb9bSAndroid Build Coastguard Worker int
569*663afb9bSAndroid Build Coastguard Worker tinytest_get_verbosity_(void)
570*663afb9bSAndroid Build Coastguard Worker {
571*663afb9bSAndroid Build Coastguard Worker 	return opt_verbosity;
572*663afb9bSAndroid Build Coastguard Worker }
573*663afb9bSAndroid Build Coastguard Worker 
574*663afb9bSAndroid Build Coastguard Worker void
575*663afb9bSAndroid Build Coastguard Worker tinytest_set_test_failed_(void)
576*663afb9bSAndroid Build Coastguard Worker {
577*663afb9bSAndroid Build Coastguard Worker 	if (opt_verbosity <= 0 && cur_test_name) {
578*663afb9bSAndroid Build Coastguard Worker 		if (opt_verbosity==0) puts("");
579*663afb9bSAndroid Build Coastguard Worker 		printf("%s%s: ", cur_test_prefix, cur_test_name);
580*663afb9bSAndroid Build Coastguard Worker 		cur_test_name = NULL;
581*663afb9bSAndroid Build Coastguard Worker 	}
582*663afb9bSAndroid Build Coastguard Worker 	cur_test_outcome = FAIL;
583*663afb9bSAndroid Build Coastguard Worker }
584*663afb9bSAndroid Build Coastguard Worker 
585*663afb9bSAndroid Build Coastguard Worker void
586*663afb9bSAndroid Build Coastguard Worker tinytest_set_test_skipped_(void)
587*663afb9bSAndroid Build Coastguard Worker {
588*663afb9bSAndroid Build Coastguard Worker 	if (cur_test_outcome==OK)
589*663afb9bSAndroid Build Coastguard Worker 		cur_test_outcome = SKIP;
590*663afb9bSAndroid Build Coastguard Worker }
591*663afb9bSAndroid Build Coastguard Worker 
592*663afb9bSAndroid Build Coastguard Worker char *
593*663afb9bSAndroid Build Coastguard Worker tinytest_format_hex_(const void *val_, unsigned long len)
594*663afb9bSAndroid Build Coastguard Worker {
595*663afb9bSAndroid Build Coastguard Worker 	const unsigned char *val = val_;
596*663afb9bSAndroid Build Coastguard Worker 	char *result, *cp;
597*663afb9bSAndroid Build Coastguard Worker 	size_t i;
598*663afb9bSAndroid Build Coastguard Worker 
599*663afb9bSAndroid Build Coastguard Worker 	if (!val)
600*663afb9bSAndroid Build Coastguard Worker 		return strdup("null");
601*663afb9bSAndroid Build Coastguard Worker 	if (!(result = malloc(len*2+1)))
602*663afb9bSAndroid Build Coastguard Worker 		return strdup("<allocation failure>");
603*663afb9bSAndroid Build Coastguard Worker 	cp = result;
604*663afb9bSAndroid Build Coastguard Worker 	for (i=0;i<len;++i) {
605*663afb9bSAndroid Build Coastguard Worker 		*cp++ = "0123456789ABCDEF"[val[i] >> 4];
606*663afb9bSAndroid Build Coastguard Worker 		*cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
607*663afb9bSAndroid Build Coastguard Worker 	}
608*663afb9bSAndroid Build Coastguard Worker 	*cp = 0;
609*663afb9bSAndroid Build Coastguard Worker 	return result;
610*663afb9bSAndroid Build Coastguard Worker }
611