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