static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ static int n_ok = 0; /**< Number of tests that have passed */ static int n_bad = 0; /**< Number of tests that have failed. */ static int n_skipped = 0; /**< Number of tests that have been skipped. */
static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ staticunsigned int opt_timeout = DEFAULT_TESTCASE_TIMEOUT; /**< Timeout for every test (using alarm()) */ const char *verbosity_flag = "";
conststruct testlist_alias_t *cfg_aliases=NULL;
enum outcome { SKIP=2, OK=1, FAIL=0 }; static enum outcome cur_test_outcome = 0; const char *cur_test_prefix = NULL; /**< prefix of the current test group */ /** Name of the current test, if we haven't logged is yet. Used for --quiet */ const char *cur_test_name = NULL;
staticvoid usage(struct testgroup_t *groups, int list_groups)
__attribute__((noreturn)); static int process_test_option(struct testgroup_t *groups, const char *test);
#ifdef _WIN32 /* Copy of argv[0] for win32. */ static char commandname[MAX_PATH+1];
static enum outcome
testcase_run_in_thread_(conststruct testcase_t *testcase, void *env)
{ /* We will never run testcase in a new thread when the
timeout is set to zero */
assert(opt_timeout);
DWORD ret, tid;
HANDLE handle; struct timeout_thread_args args = {
&(testcase->fn),
env
};
handle =CreateThread(NULL, 0, timeout_thread_proc_,
(LPVOID)&args, 0, &tid);
ret = WaitForSingleObject(handle, opt_timeout * 1000U);
if (ret == WAIT_OBJECT_0) {
ret = 0;
if (!GetExitCodeThread(handle, &ret)) {
printf("GetExitCodeThread failed\n");
ret = 1;
}
} else if (ret == WAIT_TIMEOUT) {
printf("timeout\n");
} else {
printf("Wait failed\n");
}
CloseHandle(handle);
if (ret == 0) return OK; else if (ret == MAGIC_EXITCODE) return SKIP; else return FAIL;
} #else staticunsigned int testcase_set_timeout_(void)
{ return alarm(opt_timeout);
}
staticunsigned int testcase_reset_timeout_(void)
{ return alarm(0);
} #endif
static enum outcome
testcase_run_bare_(conststruct testcase_t *testcase)
{ void *env = NULL;
int outcome;
if (testcase->setup) {
env = testcase->setup->setup_fn(testcase);
if (!env) return FAIL; else if (env == (void*)TT_SKIP) return SKIP;
}
if (!in_tinytest_main) {
printf("\nERROR. On Windows, testcase_run_forked_ must be" " called from within tinytest_main.\n");
abort();
}
if (opt_verbosity>0)
printf("[forking] ");
int
tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag)
{
int i, j;
size_t length = LONGEST_TEST_NAME;
char fullname[LONGEST_TEST_NAME];
int found=0;
if (strstr(arg, ".."))
length = strstr(arg,"..")-arg;
for (i=0; groups[i].prefix; ++i) {
for (j=0; groups[i].cases[j].name; ++j) { struct testcase_t *testcase = &groups[i].cases[j];
snprintf(fullname, sizeof(fullname), "%s%s",
groups[i].prefix, testcase->name);
if (!flag) { /* Hack! */
printf(" %s", fullname);
if (testcase->flags & TT_OFF_BY_DEFAULT)
puts(" (Off by default)"); else if (testcase->flags & TT_SKIP)
puts(" (DISABLED)"); else
puts("");
}
if (!strncmp(fullname, arg, length)) {
if (set)
testcase->flags |= flag; else
testcase->flags &= ~flag;
++found;
}
}
} return found;
}
staticvoid
usage(struct testgroup_t *groups, int list_groups)
{
puts("Options are: [--verbose|--quiet|--terse] [--no-fork] [--timeout <sec>]");
puts(" Specify tests by name, or using a prefix ending with '..'");
puts(" To skip a test, prefix its name with a colon.");
puts(" To enable a disabled test, prefix its name with a plus.");
puts(" Use --list-tests for a list of tests.");
if (list_groups) {
puts("Known tests are:");
tinytest_set_flag_(groups, "..", 1, 0);
}
exit(0);
}
static int
process_test_alias(struct testgroup_t *groups, const char *test)
{
int i, j, n, r;
for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) {
if (!strcmp(cfg_aliases[i].name, test)) {
n = 0;
for (j = 0; cfg_aliases[i].tests[j]; ++j) {
r = process_test_option(groups, cfg_aliases[i].tests[j]);
if (r<0) return -1;
n += r;
} return n;
}
}
printf("No such test alias as @%s!",test); return -1;
}
static int
process_test_option(struct testgroup_t *groups, const char *test)
{
int flag = TT_ENABLED_;
int n = 0;
if (test[0] == '@') { return process_test_alias(groups, test + 1);
} else if (test[0] == ':') {
++test;
flag = TT_SKIP;
} else if (test[0] == '+') {
++test;
++n;
if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) {
printf("No such test as %s!\n", test); return -1;
}
} else {
++n;
}
if (!tinytest_set_flag_(groups, test, 1, flag)) {
printf("No such test as %s!\n", test); return -1;
} return n;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.