diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-09-19 16:37:07 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-09-19 19:40:32 +0200 |
commit | e5cdd62624342180a16630b4f6b1d604f6e6e581 (patch) | |
tree | 71edb7e9e1853e4c3edcc22d16c066c0d5609a61 /lib | |
parent | b3525129535c6e8e3588f63960e2296d598f6e9a (diff) |
lib/drmtest: igt_assert|require with format strings
v2: Add a comment about the pitfalls around va_list handling.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/drmtest.c | 43 | ||||
-rw-r--r-- | lib/drmtest.h | 35 |
2 files changed, 65 insertions, 13 deletions
diff --git a/lib/drmtest.c b/lib/drmtest.c index 3d89047a..7c3c0af7 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -876,11 +876,34 @@ void igt_skip(const char *f, ...) } void __igt_skip_check(const char *file, const int line, - const char *func, const char *check) + const char *func, const char *check, + const char *f, ...) { - igt_skip("Test requirement not met in function %s, file %s:%i:\n" - "Test requirement: (%s)\n", - func, file, line, check); + va_list args; + + if (f) { + char buf[4096]; + int length; + + /* + * Important: va_list argument lists can't be used twice, so we + * can't first do an vsnprintf call to size the temporary + * storage correctly. Pick the easy solution with a static + * buffer and an asssert. + */ + va_start(args, f); + length = vsnprintf(buf, sizeof(buf), f, args); + assert(length < sizeof(buf) - 1); + va_end(args); + + igt_skip("Test requirement not met in function %s, file %s:%i:\n" + "Test requirement: (%s)\n%s", + func, file, line, check, buf); + } else { + igt_skip("Test requirement not met in function %s, file %s:%i:\n" + "Test requirement: (%s)\n", + func, file, line, check); + } } void igt_success(void) @@ -927,11 +950,21 @@ static bool run_under_gdb(void) } void __igt_fail_assert(int exitcode, const char *file, - const int line, const char *func, const char *assertion) + const int line, const char *func, const char *assertion, + const char *f, ...) { + va_list args; + printf("Test assertion failure function %s, file %s:%i:\n" "Failed assertion: %s\n", func, file, line, assertion); + + if (f) { + va_start(args, f); + vprintf(f, args); + va_end(args); + } + if (run_under_gdb()) abort(); igt_fail(exitcode); diff --git a/lib/drmtest.h b/lib/drmtest.h index 332e704b..cd706f0d 100644 --- a/lib/drmtest.h +++ b/lib/drmtest.h @@ -123,15 +123,15 @@ bool __igt_run_subtest(const char *subtest_name); */ #define igt_tokencat2(x, y) x ## y #define igt_tokencat(x, y) igt_tokencat2(x, y) -#define __igt_subtest_f(tmp, format, args...) \ +#define __igt_subtest_f(tmp, format...) \ for (char tmp [256]; \ snprintf( tmp , sizeof( tmp ), \ - format, args), \ + format), \ __igt_run_subtest( tmp ) && \ (setjmp(igt_subtest_jmpbuf) == 0); \ igt_success()) -#define igt_subtest_f(f, a...) \ - __igt_subtest_f(igt_tokencat(__tmpchar, __LINE__), f, a) +#define igt_subtest_f(f...) \ + __igt_subtest_f(igt_tokencat(__tmpchar, __LINE__), f) #define igt_subtest(name) for (; __igt_run_subtest((name)) && \ (setjmp(igt_subtest_jmpbuf) == 0); \ igt_success()) @@ -145,8 +145,10 @@ const char *igt_subtest_name(void); * For normal tests without subtest it will directly exit. */ __attribute__((format(printf, 1, 2))) void igt_skip(const char *f, ...); +__attribute__((format(printf, 5, 6))) void __igt_skip_check(const char *file, const int line, - const char *func, const char *check); + const char *func, const char *check, + const char *format, ...); /** * igt_success - complete a (subtest) as successfull * @@ -162,8 +164,10 @@ void igt_success(void); * presuming that some mandatory setup failed. */ void igt_fail(int exitcode) __attribute__((noreturn)); +__attribute__((format(printf, 6, 7))) void __igt_fail_assert(int exitcode, const char *file, - const int line, const char *func, const char *assertion) + const int line, const char *func, const char *assertion, + const char *format, ...) __attribute__((noreturn)); /** * igt_exit - exit() for igts @@ -179,7 +183,14 @@ void igt_exit(void) __attribute__((noreturn)); * * Should be used everywhere where a test checks results. */ -#define igt_assert(expr) do { if (!(expr)) __igt_fail_assert(99, __FILE__, __LINE__, __func__, #expr ); } while (0) +#define igt_assert(expr) \ + do { if (!(expr)) \ + __igt_fail_assert(99, __FILE__, __LINE__, __func__, #expr , NULL); \ + } while (0) +#define igt_assert_f(expr, f...) \ + do { if (!(expr)) \ + __igt_fail_assert(99, __FILE__, __LINE__, __func__, #expr , f); \ + } while (0) /** * igt_require - skip a (sub-)test if a condition is not met * @@ -187,7 +198,15 @@ void igt_exit(void) __attribute__((noreturn)); * code control flow. */ #define igt_require(expr) igt_skip_on(!(expr)) -#define igt_skip_on(expr) do { if ((expr)) __igt_skip_check(__FILE__, __LINE__, __func__, #expr ); } while (0) +#define igt_skip_on(expr) \ + do { if ((expr)) \ + __igt_skip_check(__FILE__, __LINE__, __func__, #expr , NULL); \ + } while (0) +#define igt_require_f(expr, f...) igt_skip_on_f(!(expr), f) +#define igt_skip_on_f(expr, f...) \ + do { if ((expr)) \ + __igt_skip_check(__FILE__, __LINE__, __func__, #expr , f); \ + } while (0) bool __igt_fixture(void); void __igt_fixture_complete(void); |