[Intel-gfx] [PATCH 3/7] lib/drmtest: skip/fail handling

Daniel Vetter daniel.vetter at ffwll.ch
Mon Aug 12 11:09:57 CEST 2013


Exitcode handling in igt testcases has too ugly facets in combination
with subtests:

- When individual subtest needed to be skipped for different reasons
  we need to painstakingly thread this information through the test to
  make sure that we still succeed if just one testcase worked (for
  running it with the simple automake test runner in igt). But it also
  needs to correctly report the skip exit value if only this one
  skipped testcase has been run (e.g. when run with piglit or in QA's
  test infrastructure).

- We'd prefer to easily skip (and also fail) subtests without
  hampering other subtests. Again threading the return value of each
  subtest through the code is cumbersome.

To simplify test case writing use longjmps to be able to get out of
subcases easily. But since longjmps are funny things thug it all away
into the newly added drmtest_subtest_block macro.

Note that if drmtest_skip is called outside of a subtest, but in a
testcase with subtests all subsequent subtests will be automatically
skipped.

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 lib/drmtest.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 lib/drmtest.h | 10 +++++++-
 2 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/lib/drmtest.c b/lib/drmtest.c
index cae07a2..767c8dc 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 ada8e81..13e25bb 100644
--- a/lib/drmtest.h
+++ b/lib/drmtest.h
@@ -32,6 +32,7 @@
 #include <errno.h>
 #include <stdbool.h>
 #include <cairo.h>
+#include <setjmp.h>
 
 #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);
-- 
1.8.3.2




More information about the Intel-gfx mailing list