diff --git a/lib/drmtest.c b/lib/drmtest.c index cae07a27..767c8dc8 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -657,6 +657,9 @@ void drmtest_stop_signal_helper(void) /* subtests helpers */ static bool list_subtests = false; static char *run_single_subtest = NULL; +static bool in_subtest = false; +static bool test_with_subtests = false; +static bool skip_subtests_henceforth = false; void drmtest_subtest_init(int argc, char **argv) { @@ -667,6 +670,8 @@ void drmtest_subtest_init(int argc, char **argv) {NULL, 0, 0, 0,} }; + test_with_subtests = true; + /* supress getopt errors about unknown options */ opterr = 0; /* restrict the option parsing to long option names to avoid collisions @@ -695,16 +700,21 @@ out: */ bool drmtest_run_subtest(const char *subtest_name) { + assert(in_subtest == false); + if (list_subtests) { printf("%s\n", subtest_name); return false; } + if (skip_subtests_henceforth) + return false; + if (!run_single_subtest) { - return true; + return in_subtest = true; } else { if (strcmp(subtest_name, run_single_subtest) == 0) - return true; + return in_subtest = true; return false; } @@ -715,6 +725,69 @@ bool drmtest_only_list_subtests(void) return list_subtests; } +static bool skipped_one = false; +static bool succeeded_one = false; +static bool failed_one = false; +static int drmtest_exitcode; + +static void exit_subtest(void) __attribute__((noreturn)); +static void exit_subtest(void) +{ + in_subtest = false; + longjmp(drmtest_subtest_jmpbuf, 1); +} + +void drmtest_skip(void) +{ + skipped_one = true; + if (in_subtest) + exit_subtest(); + else if (test_with_subtests) + skip_subtests_henceforth = true; + else + exit(77); +} + +void drmtest_success(void) +{ + succeeded_one = true; + if (in_subtest) + exit_subtest(); +} + +void drmtest_fail(int exitcode) +{ + assert(exitcode != 0 && exitcode != 77); + + if (!failed_one) + drmtest_exitcode = exitcode; + + failed_one = true; + + if (in_subtest) + exit_subtest(); + else { + assert(!test_with_subtests); + exit(exitcode); + } +} + +int drmtest_retval(void) +{ + if (drmtest_only_list_subtests()) + return 0; + + /* Calling this without calling one of the above is a failure */ + assert(skipped_one || succeeded_one || failed_one); + + if (failed_one) + return drmtest_exitcode; + else if (succeeded_one) + return 0; + else + return 77; +} + static bool env_set(const char *env_var, bool default_value) { char *val; diff --git a/lib/drmtest.h b/lib/drmtest.h index ada8e81c..13e25bb1 100644 --- a/lib/drmtest.h +++ b/lib/drmtest.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "xf86drm.h" #include "xf86drmMode.h" @@ -93,10 +94,17 @@ void drmtest_permute_array(void *array, unsigned size, void drmtest_progress(const char *header, uint64_t i, uint64_t total); /* subtest infrastructure */ +jmp_buf drmtest_subtest_jmpbuf; void drmtest_subtest_init(int argc, char **argv); bool drmtest_run_subtest(const char *subtest_name); -#define drmtest_subtest_block(name) if (drmtest_run_subtest((name))) +#define drmtest_subtest_block(name) for (; drmtest_run_subtest((name)) && \ + (setjmp(drmtest_subtest_jmpbuf) == 0); \ + drmtest_success()) bool drmtest_only_list_subtests(void); +void drmtest_skip(void); +void drmtest_success(void); +void drmtest_fail(int exitcode) __attribute__((noreturn)); +int drmtest_retval(void); /* helpers to automatically reduce test runtime in simulation */ bool drmtest_run_in_simulation(void);