2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2003 Net Integration Technologies, Inc.
5 * Part of an automated testing framework. See wvtest.h.
8 #include "wvautoconf.h"
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 "
40 return (int)VALGRIND_COUNT_ERRORS
;
45 int leaked
= 0, dubious
= 0, reachable
= 0, suppressed
= 0;
46 VALGRIND_DO_LEAK_CHECK
;
47 VALGRIND_COUNT_LEAKS(leaked
, dubious
, reachable
, suppressed
);
48 printf("memleaks: sure:%d dubious:%d reachable:%d suppress:%d\n",
49 leaked
, dubious
, reachable
, suppressed
);
52 // dubious+reachable are normally non-zero because of globals...
53 // return leaked+dubious+reachable;
57 // Return 1 if no children are running or zombies, 0 if there are any running
58 // or zombie children.
59 // Will wait for any already-terminated children first.
60 // Passes if no rogue children were running, fails otherwise.
61 // If your test gets a failure in here, either you're not killing all your
62 // children, or you're not calling waitpid(2) on all of them.
63 static bool no_running_children()
68 // Acknowledge and complain about any zombie children
72 wait_result
= waitpid(-1, &status
, WNOHANG
);
77 snprintf(buf
, sizeof(buf
) - 1, "%d", wait_result
);
78 buf
[sizeof(buf
)-1] = '\0';
79 WVFAILEQ("Unclaimed dead child process", buf
);
81 } while (wait_result
> 0);
83 // There should not be any running children, so waitpid should return -1
84 WVPASSEQ(errno
, ECHILD
);
85 WVPASSEQ(wait_result
, -1);
86 return (wait_result
== -1 && errno
== ECHILD
);
92 WvTest
*WvTest::first
, *WvTest::last
;
93 int WvTest::fails
, WvTest::runs
;
94 time_t WvTest::start_time
;
95 bool WvTest::run_twice
= false;
97 void WvTest::alarm_handler(int)
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;
117 WvTest::WvTest(const char *_descr
, const char *_idstr
, MainFunc
*_main
,
120 idstr(pathstrip(_idstr
)),
133 static bool prefix_match(const char *s
, const char * const *prefixes
)
135 for (const char * const *prefix
= prefixes
; prefix
&& *prefix
; prefix
++)
137 if (!strncasecmp(s
, *prefix
, strlen(*prefix
)))
144 int WvTest::run_all(const char * const *prefixes
)
146 int old_valgrind_errs
= 0, new_valgrind_errs
;
147 int old_valgrind_leaks
= 0, new_valgrind_leaks
;
150 /* I should be doing something to do with SetTimer here,
151 * not sure exactly what just yet */
153 char *disable(getenv("WVTEST_DISABLE_TIMEOUT"));
154 if (disable
!= NULL
&& disable
[0] != '\0' && disable
[0] != '0')
155 signal(SIGALRM
, SIG_IGN
);
157 signal(SIGALRM
, alarm_handler
);
158 alarm(MAX_TEST_TIME
);
160 start_time
= time(NULL
);
162 // make sure we can always start out in the same directory, so tests have
163 // access to their files. If a test uses chdir(), we want to be able to
166 if (!getcwd(wd
, sizeof(wd
)))
169 const char *slowstr1
= getenv("WVTEST_MIN_SLOWNESS");
170 const char *slowstr2
= getenv("WVTEST_MAX_SLOWNESS");
171 int min_slowness
= 0, max_slowness
= 65535;
172 if (slowstr1
) min_slowness
= atoi(slowstr1
);
173 if (slowstr2
) max_slowness
= atoi(slowstr2
);
178 char *parallel_str
= getenv("WVTEST_PARALLEL");
180 run_twice
= atoi(parallel_str
) > 0;
183 // there are lots of fflush() calls in here because stupid win32 doesn't
184 // flush very often by itself.
186 for (WvTest
*cur
= first
; cur
; cur
= cur
->next
)
188 if (cur
->slowness
<= max_slowness
189 && cur
->slowness
>= min_slowness
191 || prefix_match(cur
->idstr
, prefixes
)
192 || prefix_match(cur
->descr
, prefixes
)))
198 // I see everything twice!
199 printf("Running test in parallel.\n");
204 printf("\nTesting \"%s\" in %s:\n", cur
->descr
, cur
->idstr
);
210 new_valgrind_errs
= memerrs();
211 WVPASS(new_valgrind_errs
== old_valgrind_errs
);
212 old_valgrind_errs
= new_valgrind_errs
;
214 new_valgrind_leaks
= memleaks();
215 WVPASS(new_valgrind_leaks
== old_valgrind_leaks
);
216 old_valgrind_leaks
= new_valgrind_leaks
;
227 // I see everything once!
228 printf("Child exiting.\n");
233 printf("Waiting for child to exit.\n");
235 while ((result
= waitpid(child
, NULL
, 0)) == -1 &&
237 printf("Waitpid interrupted, retrying.\n");
242 WVPASS(no_running_children());
246 if (prefixes
&& *prefixes
)
247 printf("WvTest: WARNING: only ran tests starting with "
248 "specifed prefix(es).\n");
250 printf("WvTest: ran all tests.\n");
251 printf("WvTest: %d test%s, %d failure%s.\n",
252 runs
, runs
==1 ? "" : "s",
253 fails
, fails
==1 ? "": "s");
260 // If we aren't running in parallel, we want to output the name of the test
261 // before we run it, so we know what happened if it crashes. If we are
262 // running in parallel, outputting this information in multiple printf()s
263 // can confuse parsers, so we want to output everything in one printf().
265 // This function gets called by both start() and check(). If we're not
266 // running in parallel, just print the data. If we're running in parallel,
267 // and we're starting a test, save a copy of the file/line/description until
268 // the test is done and we can output it all at once.
270 // Yes, this is probably the worst API of all time.
271 void WvTest::print_result(bool start
, const char *_file
, int _line
,
272 const char *_condstr
, bool result
)
275 static char *condstr
;
284 file
= strdup(pathstrip(_file
));
285 condstr
= strdup(_condstr
);
288 for (char *cptr
= condstr
; *cptr
; cptr
++)
290 if (!isprint((unsigned char)*cptr
))
295 const char *result_str
= result
? "ok\n" : "FAILED\n";
299 printf(TEST_START_FORMAT
"%s", file
, line
, condstr
, result_str
);
304 printf(TEST_START_FORMAT
, file
, line
, condstr
);
306 printf("%s", result_str
);
316 file
= condstr
= NULL
;
321 void WvTest::start(const char *file
, int line
, const char *condstr
)
323 // Either print the file, line, and condstr, or save them for later.
324 print_result(true, file
, line
, condstr
, 0);
328 void WvTest::check(bool cond
)
331 alarm(MAX_TEST_TIME
); // restart per-test timeout
333 if (!start_time
) start_time
= time(NULL
);
335 if (time(NULL
) - start_time
> MAX_TOTAL_TIME
)
337 printf("\n! WvTest Total run time exceeded %d seconds! FAILED\n",
345 print_result(false, NULL
, 0, NULL
, cond
);
351 if (getenv("WVTEST_DIE_FAST"))
357 bool WvTest::start_check_eq(const char *file
, int line
,
358 const char *a
, const char *b
, bool expect_pass
)
363 size_t len
= strlen(a
) + strlen(b
) + 8 + 1;
364 char *str
= new char[len
];
365 sprintf(str
, "[%s] %s [%s]", a
, expect_pass
? "==" : "!=", b
);
367 start(file
, line
, str
);
370 bool cond
= !strcmp(a
, b
);
379 bool WvTest::start_check_eq(const char *file
, int line
,
380 int a
, int b
, bool expect_pass
)
382 size_t len
= 128 + 128 + 8 + 1;
383 char *str
= new char[len
];
384 sprintf(str
, "%d %s %d", a
, expect_pass
? "==" : "!=", b
);
386 start(file
, line
, str
);
389 bool cond
= (a
== b
);
398 bool WvTest::start_check_lt(const char *file
, int line
,
399 const char *a
, const char *b
)
404 size_t len
= strlen(a
) + strlen(b
) + 8 + 1;
405 char *str
= new char[len
];
406 sprintf(str
, "[%s] < [%s]", a
, b
);
408 start(file
, line
, str
);
411 bool cond
= strcmp(a
, b
) < 0;
417 bool WvTest::start_check_lt(const char *file
, int line
, int a
, int b
)
419 size_t len
= 128 + 128 + 8 + 1;
420 char *str
= new char[len
];
421 sprintf(str
, "%d < %d", a
, b
);
423 start(file
, line
, str
);