2 * Definitions for Wine C unit tests.
4 * Copyright (C) 2002 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #ifndef __WINE_WINE_TEST_H
22 #define __WINE_WINE_TEST_H
28 #include <wine/debug.h>
30 #ifdef __WINE_CONFIG_H
31 #error config.h should not be used in Wine tests
33 #ifdef __WINE_WINE_UNICODE_H
34 #error wine/unicode.h should not be used in Wine tests
37 #ifndef INVALID_FILE_ATTRIBUTES
38 #define INVALID_FILE_ATTRIBUTES (~0u)
40 #ifndef INVALID_SET_FILE_POINTER
41 #define INVALID_SET_FILE_POINTER (~0u)
45 extern int winetest_debug
;
47 /* trace timing information */
48 extern int winetest_time
;
50 /* running in interactive mode? */
51 extern int winetest_interactive
;
53 /* report successful tests (BOOL) */
54 extern int winetest_report_success
;
56 /* silence todos and skips above this threshold */
57 extern int winetest_mute_threshold
;
59 /* current platform */
60 extern const char *winetest_platform
;
62 extern void winetest_set_location( const char* file
, int line
);
63 extern void winetest_subtest( const char* name
);
64 extern void winetest_ignore_exceptions( BOOL ignore
);
65 extern void winetest_start_todo( int is_todo
);
66 extern int winetest_loop_todo(void);
67 extern void winetest_end_todo(void);
68 extern int winetest_get_mainargs( char*** pargv
);
69 extern LONG
winetest_get_failures(void);
70 extern void winetest_add_failures( LONG new_failures
);
71 extern void winetest_wait_child_process( HANDLE process
);
74 #define START_TEST(name) \
75 static void func_##name(void); \
76 const struct test winetest_testlist[] = { { #name, func_##name }, { 0, 0 } }; \
77 static void func_##name(void)
79 #define START_TEST(name) void func_##name(void)
82 #if (defined(__x86_64__) || (defined(__aarch64__) && __has_attribute(ms_abi))) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT)
83 #define __winetest_cdecl __cdecl
84 #define __winetest_va_list __builtin_ms_va_list
86 #define __winetest_cdecl
87 #define __winetest_va_list va_list
90 extern int broken( int condition
);
91 extern int winetest_vok( int condition
, const char *msg
, __winetest_va_list ap
);
92 extern void winetest_vskip( const char *msg
, __winetest_va_list ap
);
94 extern void __winetest_cdecl
winetest_ok( int condition
, const char *msg
, ... ) __WINE_PRINTF_ATTR(2,3);
95 extern void __winetest_cdecl
winetest_skip( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
96 extern void __winetest_cdecl
winetest_win_skip( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
97 extern void __winetest_cdecl
winetest_trace( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
99 extern void __winetest_cdecl
winetest_push_context( const char *fmt
, ... ) __WINE_PRINTF_ATTR(1, 2);
100 extern void winetest_pop_context(void);
102 #ifdef WINETEST_NO_LINE_NUMBERS
103 # define subtest_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_subtest
104 # define ignore_exceptions_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_ignore_exceptions
105 # define ok_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_ok
106 # define skip_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_skip
107 # define win_skip_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_win_skip
108 # define trace_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_trace
109 # define wait_child_process_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_wait_child_process
111 # define subtest_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_subtest
112 # define ignore_exceptions_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ignore_exceptions
113 # define ok_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ok
114 # define skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_skip
115 # define win_skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_win_skip
116 # define trace_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_trace
117 # define wait_child_process_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_wait_child_process
120 #define subtest subtest_(__FILE__, __LINE__)
121 #define ignore_exceptions ignore_exceptions_(__FILE__, __LINE__)
122 #define ok ok_(__FILE__, __LINE__)
123 #define skip skip_(__FILE__, __LINE__)
124 #define win_skip win_skip_(__FILE__, __LINE__)
125 #define trace trace_(__FILE__, __LINE__)
126 #define wait_child_process wait_child_process_(__FILE__, __LINE__)
128 #define todo_if(is_todo) for (winetest_start_todo(is_todo); \
129 winetest_loop_todo(); \
131 #define todo_wine todo_if(!strcmp(winetest_platform, "wine"))
132 #define todo_wine_if(is_todo) todo_if((is_todo) && !strcmp(winetest_platform, "wine"))
136 # define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
139 #ifdef NONAMELESSUNION
141 # define U1(x) (x).u1
142 # define U2(x) (x).u2
143 # define U3(x) (x).u3
144 # define U4(x) (x).u4
145 # define U5(x) (x).u5
146 # define U6(x) (x).u6
147 # define U7(x) (x).u7
148 # define U8(x) (x).u8
161 #ifdef NONAMELESSSTRUCT
163 # define S1(x) (x).s1
164 # define S2(x) (x).s2
165 # define S3(x) (x).s3
166 # define S4(x) (x).s4
167 # define S5(x) (x).s5
178 /************************************************************************/
179 /* Below is the implementation of the various functions, to be included
180 * directly into the generated testlist.c file.
181 * It is done that way so that the dlls can build the test routines with
182 * different includes or flags if needed.
190 #if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT)
191 # define __winetest_va_start(list,arg) __builtin_ms_va_start(list,arg)
192 # define __winetest_va_end(list) __builtin_ms_va_end(list)
194 # define __winetest_va_start(list,arg) va_start(list,arg)
195 # define __winetest_va_end(list) va_end(list)
204 extern const struct test winetest_testlist
[];
207 int winetest_debug
= 1;
209 /* trace timing information */
210 int winetest_time
= 0;
211 DWORD winetest_start_time
, winetest_last_time
;
213 /* interactive mode? */
214 int winetest_interactive
= 0;
216 /* current platform */
217 const char *winetest_platform
= "windows";
219 /* report successful tests (BOOL) */
220 int winetest_report_success
= 0;
222 /* silence todos and skips above this threshold */
223 int winetest_mute_threshold
= 42;
225 /* passing arguments around */
226 static int winetest_argc
;
227 static char** winetest_argv
;
229 static const struct test
*current_test
; /* test currently being run */
231 static LONG successes
; /* number of successful tests */
232 static LONG failures
; /* number of failures */
233 static LONG skipped
; /* number of skipped test chunks */
234 static LONG todo_successes
; /* number of successful tests inside todo block */
235 static LONG todo_failures
; /* number of failures inside todo block */
236 static LONG muted_traces
; /* number of silenced traces */
237 static LONG muted_skipped
; /* same as skipped but silent */
238 static LONG muted_todo_successes
; /* same as todo_successes but silent */
240 /* counts how many times a given line printed a message */
241 static LONG line_counters
[16384];
243 /* The following data must be kept track of on a per-thread basis */
246 const char* current_file
; /* file of current check */
247 int current_line
; /* line of current check */
248 unsigned int todo_level
; /* current todo nesting level */
250 char *str_pos
; /* position in debug buffer */
251 char strings
[2000]; /* buffer for debug strings */
252 char context
[8][128]; /* data to print before messages */
253 unsigned int context_count
; /* number of context prefixes */
255 static DWORD tls_index
;
257 static struct tls_data
*get_tls_data(void)
259 struct tls_data
*data
;
262 last_error
=GetLastError();
263 data
=TlsGetValue(tls_index
);
266 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
267 data
->str_pos
= data
->strings
;
268 TlsSetValue(tls_index
,data
);
270 SetLastError(last_error
);
274 static void exit_process( int code
)
281 void winetest_set_location( const char* file
, int line
)
283 struct tls_data
*data
= get_tls_data();
284 data
->current_file
=strrchr(file
,'/');
285 if (data
->current_file
==NULL
)
286 data
->current_file
=strrchr(file
,'\\');
287 if (data
->current_file
==NULL
)
288 data
->current_file
=file
;
290 data
->current_file
++;
291 data
->current_line
=line
;
294 const char *winetest_elapsed(void)
298 if (!winetest_time
) return "";
299 winetest_last_time
= now
= GetTickCount();
300 return wine_dbg_sprintf( "%.3f", (now
- winetest_start_time
) / 1000.0);
303 static void __winetest_cdecl
winetest_printf( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
304 static void __winetest_cdecl
winetest_printf( const char *msg
, ... )
306 struct tls_data
*data
= get_tls_data();
307 __winetest_va_list valist
;
309 printf( "%s:%d:%s ", data
->current_file
, data
->current_line
, winetest_elapsed() );
310 __winetest_va_start( valist
, msg
);
311 vprintf( msg
, valist
);
312 __winetest_va_end( valist
);
314 static void __winetest_cdecl
winetest_print_context( const char *msgtype
)
316 struct tls_data
*data
= get_tls_data();
319 winetest_printf( "%s", msgtype
);
320 for (i
= 0; i
< data
->context_count
; ++i
)
321 printf( "%s: ", data
->context
[i
] );
324 void winetest_subtest( const char* name
)
326 winetest_printf( "Subtest %s\n", name
);
329 void winetest_ignore_exceptions( BOOL ignore
)
331 winetest_printf( "IgnoreExceptions=%d\n", ignore
? 1 : 0 );
334 int broken( int condition
)
336 return (strcmp(winetest_platform
, "windows") == 0) && condition
;
339 static LONG
winetest_add_line( void )
341 struct tls_data
*data
;
344 if (winetest_debug
> 1)
347 data
= get_tls_data();
348 index
= data
->current_line
% ARRAY_SIZE(line_counters
);
349 count
= InterlockedIncrement(line_counters
+ index
) - 1;
350 if (count
== winetest_mute_threshold
)
351 winetest_printf( "Line has been silenced after %d occurrences\n", winetest_mute_threshold
);
359 * - condition - condition to check;
360 * - msg test description;
361 * - file - test application source code file name of the check
362 * - line - test application source code file line number of the check
364 * 0 if condition does not have the expected value, 1 otherwise
366 int winetest_vok( int condition
, const char *msg
, __winetest_va_list args
)
368 struct tls_data
*data
= get_tls_data();
370 if (data
->todo_level
)
374 winetest_print_context( "Test succeeded inside todo block: " );
376 InterlockedIncrement(&todo_failures
);
381 if (!winetest_debug
||
382 winetest_add_line() < winetest_mute_threshold
)
384 if (winetest_debug
> 0)
386 winetest_print_context( "Test marked todo: " );
389 InterlockedIncrement(&todo_successes
);
392 InterlockedIncrement(&muted_todo_successes
);
400 winetest_print_context( "Test failed: " );
402 InterlockedIncrement(&failures
);
407 if (winetest_report_success
||
408 (winetest_time
&& GetTickCount() >= winetest_last_time
+ 1000))
410 winetest_printf("Test succeeded\n");
412 InterlockedIncrement(&successes
);
418 void __winetest_cdecl
winetest_ok( int condition
, const char *msg
, ... )
420 __winetest_va_list valist
;
422 __winetest_va_start(valist
, msg
);
423 winetest_vok(condition
, msg
, valist
);
424 __winetest_va_end(valist
);
427 void __winetest_cdecl
winetest_trace( const char *msg
, ... )
429 __winetest_va_list valist
;
433 if (winetest_add_line() < winetest_mute_threshold
)
435 winetest_print_context( "" );
436 __winetest_va_start(valist
, msg
);
437 vprintf( msg
, valist
);
438 __winetest_va_end(valist
);
441 InterlockedIncrement(&muted_traces
);
444 void winetest_vskip( const char *msg
, __winetest_va_list args
)
446 if (winetest_add_line() < winetest_mute_threshold
)
448 winetest_print_context( "Tests skipped: " );
450 InterlockedIncrement(&skipped
);
453 InterlockedIncrement(&muted_skipped
);
456 void __winetest_cdecl
winetest_skip( const char *msg
, ... )
458 __winetest_va_list valist
;
459 __winetest_va_start(valist
, msg
);
460 winetest_vskip(msg
, valist
);
461 __winetest_va_end(valist
);
464 void __winetest_cdecl
winetest_win_skip( const char *msg
, ... )
466 __winetest_va_list valist
;
467 __winetest_va_start(valist
, msg
);
468 if (strcmp(winetest_platform
, "windows") == 0)
469 winetest_vskip(msg
, valist
);
471 winetest_vok(0, msg
, valist
);
472 __winetest_va_end(valist
);
475 void winetest_start_todo( int is_todo
)
477 struct tls_data
*data
= get_tls_data();
478 data
->todo_level
= (data
->todo_level
<< 1) | (is_todo
!= 0);
479 data
->todo_do_loop
=1;
482 int winetest_loop_todo(void)
484 struct tls_data
*data
= get_tls_data();
485 int do_loop
=data
->todo_do_loop
;
486 data
->todo_do_loop
=0;
490 void winetest_end_todo(void)
492 struct tls_data
*data
= get_tls_data();
493 data
->todo_level
>>= 1;
496 void __winetest_cdecl
winetest_push_context( const char *fmt
, ... )
498 struct tls_data
*data
= get_tls_data();
499 __winetest_va_list valist
;
501 if (data
->context_count
< ARRAY_SIZE(data
->context
))
503 __winetest_va_start(valist
, fmt
);
504 vsnprintf( data
->context
[data
->context_count
], sizeof(data
->context
[data
->context_count
]), fmt
, valist
);
505 __winetest_va_end(valist
);
506 data
->context
[data
->context_count
][sizeof(data
->context
[data
->context_count
]) - 1] = 0;
508 ++data
->context_count
;
511 void winetest_pop_context(void)
513 struct tls_data
*data
= get_tls_data();
515 if (data
->context_count
)
516 --data
->context_count
;
519 int winetest_get_mainargs( char*** pargv
)
521 *pargv
= winetest_argv
;
522 return winetest_argc
;
525 LONG
winetest_get_failures(void)
530 void winetest_add_failures( LONG new_failures
)
532 while (new_failures
-- > 0)
533 InterlockedIncrement( &failures
);
536 void winetest_wait_child_process( HANDLE process
)
540 winetest_ok( process
!= NULL
, "No child process handle (CreateProcess failed?)\n" );
541 if (!process
) return;
543 ret
= WaitForSingleObject( process
, 30000 );
544 if (ret
== WAIT_TIMEOUT
)
545 winetest_ok( 0, "Timed out waiting for the child process\n" );
546 else if (ret
!= WAIT_OBJECT_0
)
547 winetest_ok( 0, "Could not wait for the child process: %d le=%u\n",
548 ret
, GetLastError() );
552 GetExitCodeProcess( process
, &exit_code
);
555 DWORD pid
= GetProcessId( process
);
556 winetest_printf( "unhandled exception %08x in child process %04x\n", exit_code
, pid
);
557 InterlockedIncrement( &failures
);
561 winetest_printf( "%u failures in child process\n", exit_code
);
562 while (exit_code
-- > 0)
563 InterlockedIncrement(&failures
);
568 /* Find a test by name */
569 static const struct test
*find_test( const char *name
)
571 const struct test
*test
;
575 if ((p
= strrchr( name
, '/' ))) name
= p
+ 1;
576 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
578 if (len
> 2 && !strcmp( name
+ len
- 2, ".c" )) len
-= 2;
580 for (test
= winetest_testlist
; test
->name
; test
++)
582 if (!strncmp( test
->name
, name
, len
) && !test
->name
[len
]) break;
584 return test
->name
? test
: NULL
;
588 /* Display list of valid tests */
589 static void list_tests(void)
591 const struct test
*test
;
593 printf( "Valid test names:\n" );
594 for (test
= winetest_testlist
; test
->name
; test
++)
595 printf( " %s\n", test
->name
);
599 /* Run a named test, and return exit status */
600 static int run_test( const char *name
)
602 const struct test
*test
;
605 if (!(test
= find_test( name
)))
607 printf( "Fatal: test '%s' does not exist.\n", name
);
610 tls_index
=TlsAlloc();
616 if (muted_todo_successes
|| muted_skipped
|| muted_traces
)
617 printf( "%04x:%s:%s Silenced %d todos, %d skips and %d traces.\n",
618 GetCurrentProcessId(), test
->name
, winetest_elapsed(),
619 muted_todo_successes
, muted_skipped
, muted_traces
);
620 printf( "%04x:%s:%s %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
621 GetCurrentProcessId(), test
->name
, winetest_elapsed(),
622 successes
+ failures
+ todo_successes
+ todo_failures
,
623 todo_successes
, failures
+ todo_failures
,
624 (failures
+ todo_failures
!= 1) ? "failures" : "failure",
627 status
= (failures
+ todo_failures
< 255) ? failures
+ todo_failures
: 255;
632 /* Display usage and exit */
633 static void usage( const char *argv0
)
635 printf( "Usage: %s test_name\n\n", argv0
);
640 /* trap unhandled exceptions */
641 static LONG CALLBACK
exc_filter( EXCEPTION_POINTERS
*ptrs
)
643 struct tls_data
*data
= get_tls_data();
645 if (data
->current_file
)
646 printf( "%s:%d: this is the last test seen before the exception\n",
647 data
->current_file
, data
->current_line
);
648 printf( "%04x:%s:%s unhandled exception %08x at %p\n",
649 GetCurrentProcessId(), current_test
->name
, winetest_elapsed(),
650 ptrs
->ExceptionRecord
->ExceptionCode
, ptrs
->ExceptionRecord
->ExceptionAddress
);
652 return EXCEPTION_EXECUTE_HANDLER
;
655 /* check if we're running under wine */
656 static BOOL
running_under_wine(void)
658 HMODULE module
= GetModuleHandleA( "ntdll.dll" );
659 if (!module
) return FALSE
;
660 return (GetProcAddress( module
, "wine_server_call" ) != NULL
);
664 void _fpreset(void) {} /* override the mingw fpu init code */
668 int main( int argc
, char **argv
)
672 setvbuf (stdout
, NULL
, _IONBF
, 0);
674 winetest_argc
= argc
;
675 winetest_argv
= argv
;
677 if (GetEnvironmentVariableA( "WINETEST_PLATFORM", p
, sizeof(p
) ))
678 winetest_platform
= strdup(p
);
679 else if (running_under_wine())
680 winetest_platform
= "wine";
682 if (GetEnvironmentVariableA( "WINETEST_DEBUG", p
, sizeof(p
) )) winetest_debug
= atoi(p
);
683 if (GetEnvironmentVariableA( "WINETEST_INTERACTIVE", p
, sizeof(p
) )) winetest_interactive
= atoi(p
);
684 if (GetEnvironmentVariableA( "WINETEST_REPORT_SUCCESS", p
, sizeof(p
) )) winetest_report_success
= atoi(p
);
685 if (GetEnvironmentVariableA( "WINETEST_TIME", p
, sizeof(p
) )) winetest_time
= atoi(p
);
686 winetest_last_time
= winetest_start_time
= GetTickCount();
688 if (!strcmp( winetest_platform
, "windows" )) SetUnhandledExceptionFilter( exc_filter
);
689 if (!winetest_interactive
) SetErrorMode( SEM_FAILCRITICALERRORS
| SEM_NOGPFAULTERRORBOX
);
693 if (winetest_testlist
[0].name
&& !winetest_testlist
[1].name
) /* only one test */
694 return run_test( winetest_testlist
[0].name
);
697 if (!strcmp( argv
[1], "--list" ))
702 return run_test(argv
[1]);
705 #endif /* STANDALONE */
707 #endif /* __WINE_WINE_TEST_H */