3 * Copyright (C) 1997-2009 Net Integration Technologies, Inc.
4 * Licensed under the GNU Library General Public License, version 2.
5 * See the included file named LICENSE for license information.
24 #ifdef HAVE_VALGRIND_MEMCHECK_H
25 # include <valgrind/memcheck.h>
26 # include <valgrind/valgrind.h>
28 # define VALGRIND_COUNT_ERRORS 0
29 # define VALGRIND_DO_LEAK_CHECK
30 # define VALGRIND_COUNT_LEAKS(a,b,c,d) (a=b=c=d=0)
33 #define MAX_TEST_TIME 40 // max seconds for a single test to run
34 #define MAX_TOTAL_TIME 120*60 // max seconds for the entire suite to run
36 #define TEST_START_FORMAT "! %s:%-5d %-40s "
38 static int fails, runs;
39 static time_t start_time;
41 static void alarm_handler(int sig);
45 return (int)VALGRIND_COUNT_ERRORS;
50 int leaked = 0, dubious = 0, reachable = 0, suppressed = 0;
51 VALGRIND_DO_LEAK_CHECK;
52 VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed);
53 printf("memleaks: sure:%d dubious:%d reachable:%d suppress:%d\n",
54 leaked, dubious, reachable, suppressed);
57 // dubious+reachable are normally non-zero because of globals...
58 // return leaked+dubious+reachable;
62 // Return 1 if no children are running or zombies, 0 if there are any running
63 // or zombie children.
64 // Will wait for any already-terminated children first.
65 // Passes if no rogue children were running, fails otherwise.
66 // If your test gets a failure in here, either you're not killing all your
67 // children, or you're not calling waitpid(2) on all of them.
68 static bool no_running_children()
73 // Acknowledge and complain about any zombie children
77 wait_result = waitpid(-1, &status, WNOHANG);
82 snprintf(buf, sizeof(buf) - 1, "%d", wait_result);
83 buf[sizeof(buf)-1] = '\0';
84 WVFAILEQSTR("Unclaimed dead child process", buf);
86 } while (wait_result > 0);
88 // There should not be any running children, so waitpid should return -1
89 WVPASS(errno == ECHILD);
90 WVPASS(wait_result == -1);
91 return (wait_result == -1 && errno == ECHILD);
97 static void alarm_handler(int sig)
99 printf("\n! WvTest Current test took longer than %d seconds! FAILED\n",
106 static const char *pathstrip(const char *filename)
109 cptr = strrchr(filename, '/');
110 if (cptr) filename = cptr + 1;
111 cptr = strrchr(filename, '\\');
112 if (cptr) filename = cptr + 1;
116 static bool prefix_match(const char *s, char * const *prefixes)
119 for (prefix = prefixes; prefix && *prefix; prefix++)
121 if (!strncasecmp(s, *prefix, strlen(*prefix)))
127 static struct WvTest *wvtest_first, *wvtest_last;
129 void wvtest_register(struct WvTest *ptr)
131 if (wvtest_first == NULL)
134 wvtest_last->next = ptr;
136 wvtest_last->next = NULL;
139 int wvtest_run_all(char * const *prefixes)
141 int old_valgrind_errs = 0, new_valgrind_errs;
142 int old_valgrind_leaks = 0, new_valgrind_leaks;
145 /* I should be doing something to do with SetTimer here,
146 * not sure exactly what just yet */
148 char *disable = getenv("WVTEST_DISABLE_TIMEOUT");
149 if (disable != NULL && disable[0] != '\0' && disable[0] != '0')
150 signal(SIGALRM, SIG_IGN);
152 signal(SIGALRM, alarm_handler);
153 alarm(MAX_TEST_TIME);
155 start_time = time(NULL);
157 // make sure we can always start out in the same directory, so tests have
158 // access to their files. If a test uses chdir(), we want to be able to
161 if (!getcwd(wd, sizeof(wd)))
164 const char *slowstr1 = getenv("WVTEST_MIN_SLOWNESS");
165 const char *slowstr2 = getenv("WVTEST_MAX_SLOWNESS");
166 int min_slowness = 0, max_slowness = 65535;
167 if (slowstr1) min_slowness = atoi(slowstr1);
168 if (slowstr2) max_slowness = atoi(slowstr2);
173 /* char *parallel_str = getenv("WVTEST_PARALLEL"); */
174 /* if (parallel_str) */
175 /* run_twice = atoi(parallel_str) > 0; */
178 // there are lots of fflush() calls in here because stupid win32 doesn't
179 // flush very often by itself.
183 for (cur = wvtest_first; cur != NULL; cur = cur->next)
185 if (cur->slowness <= max_slowness
186 && cur->slowness >= min_slowness
188 || prefix_match(cur->idstr, prefixes)
189 || prefix_match(cur->descr, prefixes)))
192 // set SIGPIPE back to default, helps catch tests which don't set
193 // this signal to SIG_IGN (which is almost always what you want)
195 signal(SIGPIPE, SIG_DFL);
198 printf("\nTesting \"%s\" in %s:\n", cur->descr, cur->idstr);
204 new_valgrind_errs = memerrs();
205 WVPASS(new_valgrind_errs == old_valgrind_errs);
206 old_valgrind_errs = new_valgrind_errs;
208 new_valgrind_leaks = memleaks();
209 WVPASS(new_valgrind_leaks == old_valgrind_leaks);
210 old_valgrind_leaks = new_valgrind_leaks;
216 WVPASS(no_running_children());
222 if (prefixes && *prefixes && **prefixes)
223 printf("WvTest: WARNING: only ran tests starting with "
224 "specifed prefix(es).\n");
226 printf("WvTest: ran all tests.\n");
227 printf("WvTest: %d test%s, %d failure%s.\n",
228 runs, runs==1 ? "" : "s",
229 fails, fails==1 ? "": "s");
236 // If we aren't running in parallel, we want to output the name of the test
237 // before we run it, so we know what happened if it crashes. If we are
238 // running in parallel, outputting this information in multiple printf()s
239 // can confuse parsers, so we want to output everything in one printf().
241 // This function gets called by both start() and check(). If we're not
242 // running in parallel, just print the data. If we're running in parallel,
243 // and we're starting a test, save a copy of the file/line/description until
244 // the test is done and we can output it all at once.
246 // Yes, this is probably the worst API of all time.
247 static void print_result_str(bool start, const char *_file, int _line,
248 const char *_condstr, const char *result)
251 static char *condstr;
261 file = strdup(pathstrip(_file));
262 condstr = strdup(_condstr);
265 for (cptr = condstr; *cptr; cptr++)
267 if (!isprint((unsigned char)*cptr))
273 printf(TEST_START_FORMAT "%s\n", file, line, condstr, result);
282 file = condstr = NULL;
287 print_result(bool start, const char *file, int line,
288 const char *condstr, bool result)
290 print_result_str(start, file, line, condstr, result ? "ok" : "FAILED");
293 void wvtest_start(const char *file, int line, const char *condstr)
295 // Either print the file, line, and condstr, or save them for later.
296 print_result(true, file, line, condstr, false);
300 void wvtest_check(bool cond, const char *reason)
303 alarm(MAX_TEST_TIME); // restart per-test timeout
305 if (!start_time) start_time = time(NULL);
307 if (time(NULL) - start_time > MAX_TOTAL_TIME)
309 printf("\n! WvTest Total run time exceeded %d seconds! FAILED\n",
317 print_result_str(false, NULL, 0, NULL, cond ? "ok" : (reason ? reason : "FAILED"));
323 if (getenv("WVTEST_DIE_FAST"))
329 bool wvtest_start_check_eq(const char *file, int line,
330 int a, int b, bool expect_pass,
331 const char *a_str, const char *b_str)
335 char *a_op = " == ", *b_op = " == ";
336 sprintf(sa, "%d", a);
337 sprintf(sb, "%d", b);
338 if (strcmp(sa, a_str) == 0)
340 if (strcmp(sb, b_str) == 0)
342 asprintf(&str, "%s%s%d %s %s%s%d", a_str, a_op, a, expect_pass ? "==" : "!=",
345 wvtest_start(file, line, str);
348 bool cond = (a == b);
352 wvtest_check(cond, NULL);
356 bool wvtest_start_check_eq_ptr(const char *file, int line,
357 void *a, void *b, bool expect_pass)
359 size_t len = 11 + 11 + 8 + 1;
360 char *str = malloc(len);
361 sprintf(str, "%p %s %p", a, expect_pass ? "==" : "!=", b);
363 wvtest_start(file, line, str);
366 bool cond = (a == b);
370 wvtest_check(cond, NULL);
375 bool wvtest_start_check_lt(const char *file, int line,
378 size_t len = 11 + 11 + 8 + 1;
379 char *str = malloc(len);
380 sprintf(str, "%d < %d", a, b);
382 wvtest_start(file, line, str);
386 wvtest_check(cond, NULL);
389 bool wvtest_start_check_eq_str(const char *file, int line,
390 const char *a, const char *b, bool expect_pass)
395 size_t len = strlen(a) + strlen(b) + 8 + 1;
396 char *str = malloc(len);
397 sprintf(str, "[%s] %s [%s]", a, expect_pass ? "==" : "!=", b);
399 wvtest_start(file, line, str);
401 bool cond = !strcmp(a, b);
405 wvtest_check(cond, NULL);
410 bool wvtest_start_check_lt_str(const char *file, int line,
411 const char *a, const char *b)
416 size_t len = strlen(a) + strlen(b) + 8 + 1;
417 char *str = malloc(len);
418 sprintf(str, "[%s] < [%s]", a, b);
420 wvtest_start(file, line, str);
423 bool cond = strcmp(a, b) < 0;
424 wvtest_check(cond, NULL);
428 int wvtest_start_check_errno(const char *file, int line,
429 const char *condstr, int retval)
431 wvtest_start(file, line, condstr);
435 wvtest_check(retval != -1, NULL);