[2/2] include: Introduce a with_context macro and use it to simplify vcomp tests. [RFC]
Sebastian Lackner
sebastian at fds-team.de
Tue Mar 7 11:29:50 CST 2017
Based on ideas by Mark Jansen.
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
The with_context macro allows to specify a format string which is printed in
case of test failures and for trace messages. Currently, to track down the
origin of a test failure, it is necessary to write down all relevant variables
in each ok message. With the new macro it is much easier:
with_context("a = %d, b = %d, c = %d", a, b, c)
{
ok(cond1, "cond1 failed\n");
ok(cond2, "cond2 failed\n");
ok(cond3, "cond3 failed\n");
}
It can also be combined with a loop like:
for (i = 0; i < 100; i++)
with_context("i = %d", i)
{
...
}
Other remarks:
* To all submaintainers, please let me know if you would be fine to use such
a macro in your test. It should only be merged if we can agree on a
concept which is fine for everyone. Also feel free to suggest a different
name or syntax if you would like to see a different mechanism for this.
* The macro uses __VA_ARGS__ which is already used in a couple of other tests.
If there is any reason why we shouldn't depend on it, please let me know.
* The macro can also be nested (strings will be separated by ":" then).
Currently it is not allowed to use ":" inside of a context string yet, but
it could be implemented later if needed.
* It is fine to use 'continue;' inside of the block, but it is not allowed to
use 'break;' (the context would not be cleared). Also, you have to be
careful when the block can be left using exception handling or gotos.
* I am NOT planning to refactor all of the Wine tests. For existing tests, it
should only be used when it significantly improves readability (for example,
tracing 3 or more variables in each call). This rule is to ensure Alexandre
and Michael Stefaniuc don't freak out. ;)
dlls/vcomp/tests/vcomp.c | 60 +++++++++++-------------------
include/wine/test.h | 91 +++++++++++++++++++++++++++++++++--------------
2 files changed, 87 insertions(+), 64 deletions(-)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 96a3d9c20a8..5aea6856ea3 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -765,6 +765,7 @@ static void CDECL for_static_simple_cb(void)
int i;
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ with_context("test %d, thread %d/%d", i, thread_num, num_threads)
{
unsigned int my_begin, my_end, begin, end;
@@ -772,10 +773,8 @@ static void CDECL for_static_simple_cb(void)
my_for_static_simple_init(FALSE, tests[i].first, tests[i].last, tests[i].step, FALSE, &my_begin, &my_end);
p_vcomp_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, FALSE, &begin, &end);
- ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
- i, thread_num, num_threads, my_begin, begin);
- ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
- i, thread_num, num_threads, my_end, end);
+ ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
+ ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
p_vcomp_for_static_end();
p_vcomp_barrier();
@@ -784,10 +783,8 @@ static void CDECL for_static_simple_cb(void)
my_for_static_simple_init(FALSE, tests[i].first, tests[i].last, tests[i].step, TRUE, &my_begin, &my_end);
p_vcomp_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, TRUE, &begin, &end);
- ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
- i, thread_num, num_threads, my_begin, begin);
- ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
- i, thread_num, num_threads, my_end, end);
+ ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
+ ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
p_vcomp_for_static_end();
p_vcomp_barrier();
@@ -798,10 +795,8 @@ static void CDECL for_static_simple_cb(void)
my_for_static_simple_init(FALSE, tests[i].last, tests[i].first, tests[i].step, FALSE, &my_begin, &my_end);
p_vcomp_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, FALSE, &begin, &end);
- ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
- i, thread_num, num_threads, my_begin, begin);
- ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
- i, thread_num, num_threads, my_end, end);
+ ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
+ ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
p_vcomp_for_static_end();
p_vcomp_barrier();
@@ -810,10 +805,8 @@ static void CDECL for_static_simple_cb(void)
my_for_static_simple_init(FALSE, tests[i].last, tests[i].first, tests[i].step, TRUE, &my_begin, &my_end);
p_vcomp_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, TRUE, &begin, &end);
- ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
- i, thread_num, num_threads, my_begin, begin);
- ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
- i, thread_num, num_threads, my_end, end);
+ ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
+ ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
p_vcomp_for_static_end();
p_vcomp_barrier();
@@ -965,6 +958,7 @@ static void CDECL for_static_cb(void)
int i;
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ with_context("test %d, thread %d/%d", i, thread_num, num_threads)
{
int my_begin, my_end, my_next, my_lastchunk;
int begin, end, next, lastchunk;
@@ -980,21 +974,16 @@ static void CDECL for_static_cb(void)
if (broken_flags & VCOMP_FOR_STATIC_BROKEN_LOOP)
{
- ok(loops == 0 || loops == 1, "test %d, thread %d/%d: expected loops == 0 or 1, got %u\n",
- i, thread_num, num_threads, loops);
+ ok(loops == 0 || loops == 1, "expected loops == 0 or 1, got %u\n", loops);
}
else
{
- ok(loops == my_loops, "test %d, thread %d/%d: expected loops == %u, got %u\n",
- i, thread_num, num_threads, my_loops, loops);
- ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %d, got %d\n",
- i, thread_num, num_threads, my_begin, begin);
- ok(end == my_end, "test %d, thread %d/%d: expected end == %d, got %d\n",
- i, thread_num, num_threads, my_end, end);
+ ok(loops == my_loops, "expected loops == %u, got %u\n", my_loops, loops);
+ ok(begin == my_begin, "expected begin == %d, got %d\n", my_begin, begin);
+ ok(end == my_end, "expected end == %d, got %d\n", my_end, end);
ok(next == my_next || broken(broken_flags & VCOMP_FOR_STATIC_BROKEN_NEXT),
- "test %d, thread %d/%d: expected next == %d, got %d\n", i, thread_num, num_threads, my_next, next);
- ok(lastchunk == my_lastchunk, "test %d, thread %d/%d: expected lastchunk == %d, got %d\n",
- i, thread_num, num_threads, my_lastchunk, lastchunk);
+ "expected next == %d, got %d\n", my_next, next);
+ ok(lastchunk == my_lastchunk, "expected lastchunk == %d, got %d\n", my_lastchunk, lastchunk);
}
p_vcomp_for_static_end();
@@ -1011,21 +1000,16 @@ static void CDECL for_static_cb(void)
if (broken_flags & VCOMP_FOR_STATIC_BROKEN_LOOP)
{
- ok(loops == 0 || loops == 1, "test %d, thread %d/%d: expected loops == 0 or 1, got %u\n",
- i, thread_num, num_threads, loops);
+ ok(loops == 0 || loops == 1, "expected loops == 0 or 1, got %u\n", loops);
}
else
{
- ok(loops == my_loops, "test %d, thread %d/%d: expected loops == %u, got %u\n",
- i, thread_num, num_threads, my_loops, loops);
- ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %d, got %d\n",
- i, thread_num, num_threads, my_begin, begin);
- ok(end == my_end, "test %d, thread %d/%d: expected end == %d, got %d\n",
- i, thread_num, num_threads, my_end, end);
+ ok(loops == my_loops, "expected loops == %u, got %u\n", my_loops, loops);
+ ok(begin == my_begin, "expected begin == %d, got %d\n", my_begin, begin);
+ ok(end == my_end, "expected end == %d, got %d\n", my_end, end);
ok(next == my_next || broken(broken_flags & VCOMP_FOR_STATIC_BROKEN_NEXT),
- "test %d, thread %d/%d: expected next == %d, got %d\n", i, thread_num, num_threads, my_next, next);
- ok(lastchunk == my_lastchunk, "test %d, thread %d/%d: expected lastchunk == %d, got %d\n",
- i, thread_num, num_threads, my_lastchunk, lastchunk);
+ "expected next == %d, got %d\n", my_next, next);
+ ok(lastchunk == my_lastchunk, "expected lastchunk == %d, got %d\n", my_lastchunk, lastchunk);
}
p_vcomp_for_static_end();
diff --git a/include/wine/test.h b/include/wine/test.h
index af602c0fac0..52e017e32ab 100644
--- a/include/wine/test.h
+++ b/include/wine/test.h
@@ -46,6 +46,20 @@
#define INVALID_SET_FILE_POINTER (~0u)
#endif
+#if defined(__x86_64__) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT)
+#define __winetest_cdecl __cdecl
+#define __winetest_va_list __builtin_ms_va_list
+#else
+#define __winetest_cdecl
+#define __winetest_va_list va_list
+#endif
+
+#ifdef __GNUC__
+# define WINETEST_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
+#else
+# define WINETEST_PRINTF_ATTR(fmt,args)
+#endif
+
/* debug level */
extern int winetest_debug;
@@ -59,6 +73,9 @@ extern void winetest_set_location( const char* file, int line );
extern void winetest_start_todo( int is_todo );
extern int winetest_loop_todo(void);
extern void winetest_end_todo(void);
+extern void __winetest_cdecl winetest_start_context( const char *msg, ... ) WINETEST_PRINTF_ATTR(1,2);
+extern int winetest_loop_context(void);
+extern void winetest_end_context(void);
extern int winetest_get_mainargs( char*** pargv );
extern LONG winetest_get_failures(void);
extern void winetest_add_failures( LONG new_failures );
@@ -86,24 +103,10 @@ static inline int winetest_strcmpW( const WCHAR *str1, const WCHAR *str2 )
#define START_TEST(name) void func_##name(void)
#endif
-#if defined(__x86_64__) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT)
-#define __winetest_cdecl __cdecl
-#define __winetest_va_list __builtin_ms_va_list
-#else
-#define __winetest_cdecl
-#define __winetest_va_list va_list
-#endif
-
extern int broken( int condition );
extern int winetest_vok( int condition, const char *msg, __winetest_va_list ap );
extern void winetest_vskip( const char *msg, __winetest_va_list ap );
-#ifdef __GNUC__
-# define WINETEST_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
-#else
-# define WINETEST_PRINTF_ATTR(fmt,args)
-#endif
-
extern void __winetest_cdecl winetest_ok( int condition, const char *msg, ... ) WINETEST_PRINTF_ATTR(2,3);
extern void __winetest_cdecl winetest_skip( const char *msg, ... ) WINETEST_PRINTF_ATTR(1,2);
extern void __winetest_cdecl winetest_win_skip( const char *msg, ... ) WINETEST_PRINTF_ATTR(1,2);
@@ -125,6 +128,9 @@ extern void __winetest_cdecl winetest_trace( const char *msg, ... ) WINETEST_PRI
#define todo_wine todo_if(!strcmp(winetest_platform, "wine"))
#define todo_wine_if(is_todo) todo_if((is_todo) && !strcmp(winetest_platform, "wine"))
+#define with_context(...) for (winetest_start_context(__VA_ARGS__); \
+ winetest_loop_context(); \
+ winetest_end_context())
#ifdef NONAMELESSUNION
# define U(x) (x).u
@@ -175,6 +181,7 @@ extern void __winetest_cdecl winetest_trace( const char *msg, ... ) WINETEST_PRI
#ifdef STANDALONE
#include <stdio.h>
+#include <string.h>
#include <excpt.h>
#if defined(__x86_64__) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT)
@@ -224,7 +231,9 @@ struct tls_data
int current_line; /* line of current check */
unsigned int todo_level; /* current todo nesting level */
int todo_do_loop;
+ int context_do_loop;
char *str_pos; /* position in debug buffer */
+ char context[2000]; /* buffer for debug context */
char strings[2000]; /* buffer for debug strings */
};
static DWORD tls_index;
@@ -307,8 +316,8 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
{
if (condition)
{
- printf( "%s:%d: Test succeeded inside todo block: ",
- data->current_file, data->current_line );
+ printf( "%s:%d%s: Test succeeded inside todo block: ",
+ data->current_file, data->current_line, data->context );
vprintf(msg, args);
InterlockedIncrement(&todo_failures);
return 0;
@@ -317,8 +326,8 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
{
if (winetest_debug > 0)
{
- printf( "%s:%d: Test marked todo: ",
- data->current_file, data->current_line );
+ printf( "%s:%d%s: Test marked todo: ",
+ data->current_file, data->current_line, data->context );
vprintf(msg, args);
}
InterlockedIncrement(&todo_successes);
@@ -329,8 +338,8 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
{
if (!condition)
{
- printf( "%s:%d: Test failed: ",
- data->current_file, data->current_line );
+ printf( "%s:%d%s: Test failed: ",
+ data->current_file, data->current_line, data->context );
vprintf(msg, args);
InterlockedIncrement(&failures);
return 0;
@@ -338,8 +347,8 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
else
{
if (report_success)
- printf( "%s:%d: Test succeeded\n",
- data->current_file, data->current_line);
+ printf( "%s:%d%s: Test succeeded\n",
+ data->current_file, data->current_line, data->context );
InterlockedIncrement(&successes);
return 1;
}
@@ -362,7 +371,7 @@ void __winetest_cdecl winetest_trace( const char *msg, ... )
if (winetest_debug > 0)
{
- printf( "%s:%d: ", data->current_file, data->current_line );
+ printf( "%s:%d%s: ", data->current_file, data->current_line, data->context );
__winetest_va_start(valist, msg);
vprintf(msg, valist);
__winetest_va_end(valist);
@@ -373,7 +382,7 @@ void winetest_vskip( const char *msg, __winetest_va_list args )
{
struct tls_data *data = get_tls_data();
- printf( "%s:%d: Tests skipped: ", data->current_file, data->current_line );
+ printf( "%s:%d%s: Tests skipped: ", data->current_file, data->current_line, data->context );
vprintf(msg, args);
skipped++;
}
@@ -418,6 +427,36 @@ void winetest_end_todo(void)
data->todo_level >>= 1;
}
+void __winetest_cdecl winetest_start_context( const char *msg, ... )
+{
+ __winetest_va_list valist;
+ struct tls_data *data = get_tls_data();
+ char *buf = data->context + strlen(data->context);
+
+ *buf++ = ':';
+ __winetest_va_start(valist, msg);
+ vsprintf(buf, msg, valist);
+ __winetest_va_end(valist);
+ if ((buf = strchr(buf, ':'))) *buf = 0;
+
+ data->context_do_loop = 1;
+}
+
+int winetest_loop_context(void)
+{
+ struct tls_data *data = get_tls_data();
+ int do_loop = data->context_do_loop;
+ data->context_do_loop = 0;
+ return do_loop;
+}
+
+void winetest_end_context(void)
+{
+ struct tls_data *data = get_tls_data();
+ char *buf = strrchr(data->context, ':');
+ *buf = 0;
+}
+
int winetest_get_mainargs( char*** pargv )
{
*pargv = winetest_argv;
@@ -616,8 +655,8 @@ static LONG CALLBACK exc_filter( EXCEPTION_POINTERS *ptrs )
struct tls_data *data = get_tls_data();
if (data->current_file)
- printf( "%s:%d: this is the last test seen before the exception\n",
- data->current_file, data->current_line );
+ printf( "%s:%d%s: this is the last test seen before the exception\n",
+ data->current_file, data->current_line, data->context );
printf( "%04x:%s: unhandled exception %08x at %p\n",
GetCurrentProcessId(), current_test->name,
ptrs->ExceptionRecord->ExceptionCode, ptrs->ExceptionRecord->ExceptionAddress );
--
2.11.0
More information about the wine-patches
mailing list