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
29 #include <wine/debug.h>
31 #ifndef INVALID_FILE_ATTRIBUTES
32 #define INVALID_FILE_ATTRIBUTES (~0u)
34 #ifndef INVALID_SET_FILE_POINTER
35 #define INVALID_SET_FILE_POINTER (~0u)
39 extern int winetest_debug
;
41 /* trace timing information */
42 extern int winetest_time
;
43 extern int winetest_start_time
, winetest_last_time
;
45 /* running in interactive mode? */
46 extern int winetest_interactive
;
48 /* report failed flaky tests as failures (BOOL) */
49 extern int winetest_report_flaky
;
51 /* report successful tests (BOOL) */
52 extern int winetest_report_success
;
54 /* silence todos and skips above this threshold */
55 extern int winetest_mute_threshold
;
57 /* current platform */
58 extern const char *winetest_platform
;
59 extern int winetest_platform_is_wine
;
61 /* use ANSI escape codes for output coloring */
62 extern int winetest_color
;
64 extern LONG winetest_successes
; /* number of successful tests */
65 extern LONG winetest_failures
; /* number of failures */
66 extern LONG winetest_flaky_failures
; /* number of failures inside flaky block */
67 extern LONG winetest_skipped
; /* number of skipped test chunks */
68 extern LONG winetest_todo_successes
; /* number of successful tests inside todo block */
69 extern LONG winetest_todo_failures
; /* number of failures inside todo block */
70 extern LONG winetest_muted_traces
; /* number of silenced traces */
71 extern LONG winetest_muted_skipped
; /* same as skipped but silent */
72 extern LONG winetest_muted_todo_successes
; /* same as todo_successes but silent */
74 /* The following data must be kept track of on a per-thread basis */
75 struct winetest_thread_data
77 const char* current_file
; /* file of current check */
78 int current_line
; /* line of current check */
79 unsigned int flaky_level
; /* current flaky nesting level */
81 unsigned int todo_level
; /* current todo nesting level */
83 char *str_pos
; /* position in debug buffer */
84 char strings
[2000]; /* buffer for debug strings */
85 char context
[8][128]; /* data to print before messages */
86 unsigned int context_count
; /* number of context prefixes */
89 extern struct winetest_thread_data
*winetest_get_thread_data(void);
90 extern void winetest_print_lock(void);
91 extern void winetest_print_unlock(void);
92 extern int winetest_vprintf( const char *msg
, va_list args
);
93 extern int winetest_get_time(void);
95 extern int winetest_get_mainargs( char*** pargv
);
96 extern void winetest_wait_child_process( HANDLE process
);
99 #define START_TEST(name) \
100 static void func_##name(void); \
101 const struct test winetest_testlist[] = { { #name, func_##name }, { 0, 0 } }; \
102 static void func_##name(void)
104 #define START_TEST(name) void func_##name(void)
107 #ifdef WINETEST_NO_LINE_NUMBERS
108 # define subtest_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_subtest
109 # define ignore_exceptions_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_ignore_exceptions
110 # define ok_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_ok
111 # define skip_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_skip
112 # define win_skip_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_win_skip
113 # define trace_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_trace
114 # define wait_child_process_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_wait_child_process
116 # define subtest_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_subtest
117 # define ignore_exceptions_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ignore_exceptions
118 # define ok_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ok
119 # define skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_skip
120 # define win_skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_win_skip
121 # define trace_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_trace
122 # define wait_child_process_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_wait_child_process
125 #define subtest subtest_(__FILE__, __LINE__)
126 #define ignore_exceptions ignore_exceptions_(__FILE__, __LINE__)
127 #define ok ok_(__FILE__, __LINE__)
128 #define skip skip_(__FILE__, __LINE__)
129 #define win_skip win_skip_(__FILE__, __LINE__)
130 #define trace trace_(__FILE__, __LINE__)
131 #define wait_child_process wait_child_process_(__FILE__, __LINE__)
133 #define flaky_if(is_flaky) for (winetest_start_flaky(is_flaky); \
134 winetest_loop_flaky(); \
135 winetest_end_flaky())
136 #define flaky flaky_if(TRUE)
137 #define flaky_wine flaky_if(winetest_platform_is_wine)
138 #define flaky_wine_if(is_flaky) flaky_if((is_flaky) && winetest_platform_is_wine)
140 #define todo_if(is_todo) for (winetest_start_todo(is_todo); \
141 winetest_loop_todo(); \
143 #define todo_wine todo_if(winetest_platform_is_wine)
144 #define todo_wine_if(is_todo) todo_if((is_todo) && winetest_platform_is_wine)
148 # define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
151 /* Records the location of the next check.
152 * See the xxx_(file, line) macros.
155 * - file - source file name of the check
156 * - line - source line number of the check
158 static inline void winetest_set_location( const char *file
, int line
)
160 struct winetest_thread_data
*data
= winetest_get_thread_data();
161 data
->current_file
=strrchr(file
,'/');
162 if (data
->current_file
==NULL
)
163 data
->current_file
=strrchr(file
,'\\');
164 if (data
->current_file
==NULL
)
165 data
->current_file
=file
;
167 data
->current_file
++;
168 data
->current_line
=line
;
171 static const char winetest_color_reset
[] = "\x1b[0m";
172 static const char winetest_color_dark_red
[] = "\x1b[31m";
173 static const char winetest_color_dark_purple
[] = "\x1b[35m";
174 static const char winetest_color_green
[] = "\x1b[32m";
175 static const char winetest_color_yellow
[] = "\x1b[33m";
176 static const char winetest_color_blue
[] = "\x1b[34m";
177 static const char winetest_color_bright_red
[] = "\x1b[1;91m";
178 static const char winetest_color_bright_purple
[] = "\x1b[1;95m";
180 static int winetest_printf( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
181 static int winetest_printf( const char *msg
, ... )
186 va_start( valist
, msg
);
187 ret
= winetest_vprintf( msg
, valist
);
193 static const char *winetest_elapsed( char *buffer
)
197 if (!winetest_time
) return "";
198 winetest_last_time
= now
= winetest_get_time();
199 sprintf( buffer
, "%.3f", (now
- winetest_start_time
) / 1000.0 );
203 static void winetest_print_location( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
204 static void winetest_print_location( const char *msg
, ... )
206 struct winetest_thread_data
*data
= winetest_get_thread_data();
210 winetest_printf( "%s:%d:%s ", data
->current_file
, data
->current_line
, winetest_elapsed( elapsed
) );
211 va_start( valist
, msg
);
212 winetest_vprintf( msg
, valist
);
216 static void winetest_print_context( const char *msgtype
)
218 struct winetest_thread_data
*data
= winetest_get_thread_data();
221 winetest_print_location( "%s", msgtype
);
222 for (i
= 0; i
< data
->context_count
; ++i
)
223 winetest_printf( "%s: ", data
->context
[i
] );
226 static inline void winetest_subtest( const char *name
)
228 winetest_print_lock();
229 winetest_print_location( "Subtest %s\n", name
);
230 winetest_print_unlock();
233 static inline void winetest_ignore_exceptions( BOOL ignore
)
235 winetest_print_lock();
236 winetest_print_location( "IgnoreExceptions=%d\n", ignore
? 1 : 0 );
237 winetest_print_unlock();
240 static inline int broken( int condition
)
242 return !winetest_platform_is_wine
&& condition
;
245 static LONG
winetest_add_line( void )
247 /* counts how many times a given line printed a message */
248 static LONG line_counters
[16384];
250 struct winetest_thread_data
*data
;
253 if (winetest_debug
> 1)
256 data
= winetest_get_thread_data();
257 index
= data
->current_line
% ARRAY_SIZE(line_counters
);
258 count
= InterlockedIncrement(line_counters
+ index
) - 1;
259 if (count
== winetest_mute_threshold
)
261 winetest_print_lock();
262 winetest_print_location( "Line has been silenced after %d occurrences\n", winetest_mute_threshold
);
263 winetest_print_unlock();
270 * Checks that a condition has the expected value, that is true except if
271 * preceded by a todo indicating the check is expected to fail.
274 * - condition - true if the check succeeded, false otherwise;
275 * - msg - failure message format;
276 * - args - arguments for the failure message
278 * 0 if condition does not have the expected value, 1 otherwise
280 static int winetest_vok( int condition
, const char *msg
, va_list args
)
282 struct winetest_thread_data
*data
= winetest_get_thread_data();
284 if (data
->todo_level
)
288 winetest_print_lock();
289 if (data
->flaky_level
)
291 if (winetest_color
) winetest_printf( winetest_color_dark_purple
);
292 winetest_print_context( "Test succeeded inside flaky todo block: " );
293 winetest_vprintf( msg
, args
);
294 InterlockedIncrement( &winetest_flaky_failures
);
298 if (winetest_color
) winetest_printf( winetest_color_dark_red
);
299 winetest_print_context( "Test succeeded inside todo block: " );
300 winetest_vprintf( msg
, args
);
301 InterlockedIncrement( &winetest_todo_failures
);
303 if (winetest_color
) winetest_printf( winetest_color_reset
);
304 winetest_print_unlock();
309 if (!winetest_debug
||
310 winetest_add_line() < winetest_mute_threshold
)
312 if (winetest_debug
> 0)
314 winetest_print_lock();
315 if (winetest_color
) winetest_printf( winetest_color_yellow
);
316 winetest_print_context( "Test marked todo: " );
317 winetest_vprintf( msg
, args
);
318 if (winetest_color
) winetest_printf( winetest_color_reset
);
319 winetest_print_unlock();
321 InterlockedIncrement( &winetest_todo_successes
);
323 else InterlockedIncrement( &winetest_muted_todo_successes
);
331 winetest_print_lock();
332 if (data
->flaky_level
)
334 if (winetest_color
) winetest_printf( winetest_color_bright_purple
);
335 winetest_print_context( "Test marked flaky: " );
336 winetest_vprintf( msg
, args
);
337 InterlockedIncrement( &winetest_flaky_failures
);
341 if (winetest_color
) winetest_printf( winetest_color_bright_red
);
342 winetest_print_context( "Test failed: " );
343 winetest_vprintf( msg
, args
);
344 InterlockedIncrement( &winetest_failures
);
346 if (winetest_color
) winetest_printf( winetest_color_reset
);
347 winetest_print_unlock();
352 if (winetest_report_success
||
353 (winetest_time
&& winetest_get_time() >= winetest_last_time
+ 1000))
355 winetest_print_lock();
356 if (winetest_color
) winetest_printf( winetest_color_green
);
357 winetest_print_location("Test succeeded\n");
358 if (winetest_color
) winetest_printf( winetest_color_reset
);
359 winetest_print_unlock();
361 InterlockedIncrement( &winetest_successes
);
367 static void winetest_ok( int condition
, const char *msg
, ... ) __WINE_PRINTF_ATTR(2,3);
368 static inline void winetest_ok( int condition
, const char *msg
, ... )
372 va_start(valist
, msg
);
373 winetest_vok(condition
, msg
, valist
);
377 static void winetest_trace( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
378 static inline void winetest_trace( const char *msg
, ... )
384 if (winetest_add_line() < winetest_mute_threshold
)
386 winetest_print_lock();
387 winetest_print_context( "" );
388 va_start(valist
, msg
);
389 winetest_vprintf( msg
, valist
);
391 winetest_print_unlock();
393 else InterlockedIncrement( &winetest_muted_traces
);
396 static void winetest_vskip( const char *msg
, va_list args
)
398 if (winetest_add_line() < winetest_mute_threshold
)
400 winetest_print_lock();
401 if (winetest_color
) winetest_printf( winetest_color_blue
);
402 winetest_print_context( "Tests skipped: " );
403 winetest_vprintf( msg
, args
);
404 if (winetest_color
) winetest_printf( winetest_color_reset
);
405 winetest_print_unlock();
406 InterlockedIncrement( &winetest_skipped
);
408 else InterlockedIncrement( &winetest_muted_skipped
);
412 * Prints a message to indicate that a group of tests is being skipped
413 * because the requirements for running them are not met.
416 * - msg - failure message format;
417 * - args - arguments for the failure message
419 static void winetest_skip( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
420 static inline void winetest_skip( const char *msg
, ... )
423 va_start(valist
, msg
);
424 winetest_vskip(msg
, valist
);
428 static void winetest_win_skip( const char *msg
, ... ) __WINE_PRINTF_ATTR(1,2);
429 static inline void winetest_win_skip( const char *msg
, ... )
432 va_start(valist
, msg
);
433 if (!winetest_platform_is_wine
)
434 winetest_vskip(msg
, valist
);
436 winetest_vok(0, msg
, valist
);
440 /* If is_flaky is true, indicates that the next test may occasionally fail due
441 * to unavoidable outside race conditions. Such failures will be flagged as
442 * flaky so they can be ignored by automated testing tools.
445 * - This is not meant to paper over race conditions within the test itself.
446 * Those are bugs and should be fixed.
447 * - This is not meant to be used for tests that normally succeed but
448 * systematically fail on a specific platform or locale.
449 * - The failures should be rare to start with. If a test fails 25% of the time
450 * it is probably wrong.
452 static inline void winetest_start_flaky( int is_flaky
)
454 struct winetest_thread_data
*data
= winetest_get_thread_data();
455 data
->flaky_level
= (data
->flaky_level
<< 1) | (is_flaky
!= 0);
456 data
->flaky_do_loop
= 1;
459 static inline int winetest_loop_flaky(void)
461 struct winetest_thread_data
*data
= winetest_get_thread_data();
462 int do_flaky
= data
->flaky_do_loop
;
463 data
->flaky_do_loop
= 0;
467 static inline void winetest_end_flaky(void)
469 struct winetest_thread_data
*data
= winetest_get_thread_data();
470 data
->flaky_level
>>= 1;
473 /* If is_todo is true, indicates that the next test is expected to fail on this
474 * platform. This is used to identify tests that are known to fail in Wine.
477 * - is_todo should never be true on Windows. To ensure this, always use
480 static inline void winetest_start_todo( int is_todo
)
482 struct winetest_thread_data
*data
= winetest_get_thread_data();
483 data
->todo_level
= (data
->todo_level
<< 1) | (is_todo
!= 0);
484 data
->todo_do_loop
=1;
487 static inline int winetest_loop_todo(void)
489 struct winetest_thread_data
*data
= winetest_get_thread_data();
490 int do_loop
=data
->todo_do_loop
;
491 data
->todo_do_loop
=0;
495 static inline void winetest_end_todo(void)
497 struct winetest_thread_data
*data
= winetest_get_thread_data();
498 data
->todo_level
>>= 1;
501 /* Adds a string to be prepended to the test traces and failure messages.
502 * This must be paired with a winetest_pop_context() call.
505 * - msg - failure message format;
506 * - args - arguments for the failure message
509 * - Failure messages must always make it possible to figure out what was being
510 * tested. While not ideal the line number can usually be used for that
511 * purpose except when the test loops on a list of test parameters. In such
512 * cases either the test parameters or the loop index should be added to the
517 * for (i = 0; i < ARRAY_SIZE(test_parameters); i++)
519 * winetest_push_context("%d", i);
521 * ok(WinAPI(test_parameters[i]), ...);
523 * winetest_pop_context();
526 static void winetest_push_context( const char *fmt
, ... ) __WINE_PRINTF_ATTR(1, 2);
527 static inline void winetest_push_context( const char *fmt
, ... )
529 struct winetest_thread_data
*data
= winetest_get_thread_data();
532 if (data
->context_count
< ARRAY_SIZE(data
->context
))
534 va_start(valist
, fmt
);
535 vsnprintf( data
->context
[data
->context_count
], sizeof(data
->context
[data
->context_count
]), fmt
, valist
);
537 data
->context
[data
->context_count
][sizeof(data
->context
[data
->context_count
]) - 1] = 0;
539 ++data
->context_count
;
542 static inline void winetest_pop_context(void)
544 struct winetest_thread_data
*data
= winetest_get_thread_data();
546 if (data
->context_count
)
547 --data
->context_count
;
550 static inline LONG
winetest_get_failures(void)
552 return winetest_failures
;
555 static inline void winetest_add_failures( LONG new_failures
)
557 while (new_failures
-- > 0) InterlockedIncrement( &winetest_failures
);
561 /************************************************************************/
562 /* Below is the implementation of the various functions, to be included
563 * directly into the generated testlist.c file.
564 * It is done that way so that the dlls can build the test routines with
565 * different includes or flags if needed.
579 extern const struct test winetest_testlist
[];
582 int winetest_debug
= 1;
584 /* trace timing information */
585 int winetest_time
= 0;
586 int winetest_start_time
, winetest_last_time
;
588 /* interactive mode? */
589 int winetest_interactive
= 0;
591 /* current platform */
592 const char *winetest_platform
= "windows";
593 int winetest_platform_is_wine
= 0;
595 /* report failed flaky tests as failures (BOOL) */
596 int winetest_report_flaky
= 0;
598 /* report successful tests (BOOL) */
599 int winetest_report_success
= 0;
601 /* silence todos and skips above this threshold */
602 int winetest_mute_threshold
= 42;
604 /* use ANSI escape codes for output coloring */
605 int winetest_color
= 0;
607 static HANDLE winetest_mutex
;
609 /* passing arguments around */
610 static int winetest_argc
;
611 static char** winetest_argv
;
613 static const struct test
*current_test
; /* test currently being run */
615 LONG winetest_successes
= 0; /* number of successful tests */
616 LONG winetest_failures
= 0; /* number of failures */
617 LONG winetest_flaky_failures
= 0; /* number of failures inside flaky block */
618 LONG winetest_skipped
= 0; /* number of skipped test chunks */
619 LONG winetest_todo_successes
= 0; /* number of successful tests inside todo block */
620 LONG winetest_todo_failures
= 0; /* number of failures inside todo block */
621 LONG winetest_muted_traces
= 0; /* number of silenced traces */
622 LONG winetest_muted_skipped
= 0; /* same as skipped but silent */
623 LONG winetest_muted_todo_successes
= 0; /* same as todo_successes but silent */
625 static DWORD tls_index
;
627 struct winetest_thread_data
*winetest_get_thread_data(void)
629 struct winetest_thread_data
*data
;
632 last_error
= GetLastError();
633 data
= TlsGetValue( tls_index
);
636 data
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
) );
637 data
->str_pos
= data
->strings
;
638 TlsSetValue( tls_index
, data
);
640 SetLastError( last_error
);
644 static void exit_process( int code
)
650 void winetest_print_lock(void)
654 if (!winetest_mutex
) return;
655 ret
= WaitForSingleObject( winetest_mutex
, 30000 );
656 if (ret
!= WAIT_OBJECT_0
&& ret
!= WAIT_ABANDONED
)
658 winetest_print_location( "could not get the print lock: %u\n", ret
);
663 void winetest_print_unlock(void)
665 if (winetest_mutex
) ReleaseMutex( winetest_mutex
);
668 int winetest_vprintf( const char *msg
, va_list args
)
670 return vprintf( msg
, args
);
673 int winetest_get_time(void)
675 return GetTickCount();
678 int winetest_get_mainargs( char ***pargv
)
680 *pargv
= winetest_argv
;
681 return winetest_argc
;
684 void winetest_wait_child_process( HANDLE process
)
688 winetest_ok( process
!= NULL
, "No child process handle (CreateProcess failed?)\n" );
689 if (!process
) return;
691 ret
= WaitForSingleObject( process
, 30000 );
692 if (ret
== WAIT_TIMEOUT
)
693 winetest_ok( 0, "Timed out waiting for the child process\n" );
694 else if (ret
!= WAIT_OBJECT_0
)
695 winetest_ok( 0, "Could not wait for the child process: %d le=%u\n",
696 (UINT
)ret
, (UINT
)GetLastError() );
700 GetExitCodeProcess( process
, &exit_code
);
703 DWORD pid
= GetProcessId( process
);
704 winetest_print_lock();
705 if (winetest_color
) winetest_printf( winetest_color_bright_red
);
706 winetest_print_location( "unhandled exception %08x in child process %04x\n", (UINT
)exit_code
, (UINT
)pid
);
707 if (winetest_color
) winetest_printf( winetest_color_reset
);
708 winetest_print_unlock();
709 InterlockedIncrement( &winetest_failures
);
713 winetest_print_lock();
714 winetest_print_location( "%u failures in child process\n", (UINT
)exit_code
);
715 winetest_print_unlock();
716 while (exit_code
-- > 0) InterlockedIncrement( &winetest_failures
);
721 /* Find a test by name */
722 static const struct test
*find_test( const char *name
)
724 const struct test
*test
;
728 if ((p
= strrchr( name
, '/' ))) name
= p
+ 1;
729 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
731 if (len
> 2 && !strcmp( name
+ len
- 2, ".c" )) len
-= 2;
733 for (test
= winetest_testlist
; test
->name
; test
++)
735 if (!strncmp( test
->name
, name
, len
) && !test
->name
[len
]) break;
737 return test
->name
? test
: NULL
;
741 /* Display list of valid tests */
742 static void list_tests(void)
744 const struct test
*test
;
746 printf( "Valid test names:\n" );
747 for (test
= winetest_testlist
; test
->name
; test
++)
748 printf( " %s\n", test
->name
);
752 /* Run a named test, and return exit status */
753 static int run_test( const char *name
)
755 const struct test
*test
;
758 if (!(test
= find_test( name
)))
760 printf( "Fatal: test '%s' does not exist.\n", name
);
763 tls_index
=TlsAlloc();
771 winetest_print_lock();
772 if (winetest_muted_todo_successes
|| winetest_muted_skipped
|| winetest_muted_traces
)
773 printf( "%04x:%s:%s Silenced %d todos, %d skips and %d traces.\n",
774 (UINT
)GetCurrentProcessId(), test
->name
, winetest_elapsed( elapsed
),
775 (UINT
)winetest_muted_todo_successes
, (UINT
)winetest_muted_skipped
, (UINT
)winetest_muted_traces
);
776 printf( "%04x:%s:%s %d tests executed (%d marked as todo, %d as flaky, %d %s), %d skipped.\n",
777 (UINT
)GetCurrentProcessId(), test
->name
, winetest_elapsed( elapsed
),
778 (UINT
)(winetest_successes
+ winetest_failures
+ winetest_flaky_failures
+ winetest_todo_successes
+ winetest_todo_failures
),
779 (UINT
)winetest_todo_successes
, (UINT
)winetest_flaky_failures
, (UINT
)(winetest_failures
+ winetest_todo_failures
),
780 (winetest_failures
+ winetest_todo_failures
!= 1) ? "failures" : "failure",
781 (UINT
)winetest_skipped
);
782 winetest_print_unlock();
784 status
= winetest_failures
+ winetest_todo_failures
;
785 if (winetest_report_flaky
) status
+= winetest_flaky_failures
;
786 if (status
> 255) status
= 255;
791 /* Display usage and exit */
792 static void usage( const char *argv0
)
794 printf( "Usage: %s test_name\n\n", argv0
);
799 /* trap unhandled exceptions */
800 static LONG CALLBACK
exc_filter( EXCEPTION_POINTERS
*ptrs
)
802 struct winetest_thread_data
*data
= winetest_get_thread_data();
805 winetest_print_lock();
806 if (data
->current_file
)
807 printf( "%s:%d: this is the last test seen before the exception\n",
808 data
->current_file
, data
->current_line
);
809 if (winetest_color
) printf( winetest_color_bright_red
);
810 printf( "%04x:%s:%s unhandled exception %08x at %p\n",
811 (UINT
)GetCurrentProcessId(), current_test
->name
, winetest_elapsed( elapsed
),
812 (UINT
)ptrs
->ExceptionRecord
->ExceptionCode
, ptrs
->ExceptionRecord
->ExceptionAddress
);
813 if (winetest_color
) printf( winetest_color_reset
);
815 winetest_print_unlock();
816 return EXCEPTION_EXECUTE_HANDLER
;
819 /* check if we're running under wine */
820 static BOOL
running_under_wine(void)
822 HMODULE module
= GetModuleHandleA( "ntdll.dll" );
823 if (!module
) return FALSE
;
824 return (GetProcAddress( module
, "wine_server_call" ) != NULL
);
828 void _fpreset(void) {} /* override the mingw fpu init code */
832 int main( int argc
, char **argv
)
836 setvbuf (stdout
, NULL
, _IONBF
, 0);
837 winetest_mutex
= CreateMutexA(NULL
, FALSE
, "winetest_print_mutex");
839 winetest_argc
= argc
;
840 winetest_argv
= argv
;
842 if (GetEnvironmentVariableA( "WINETEST_PLATFORM", p
, sizeof(p
) ))
843 winetest_platform
= strdup(p
);
844 else if (running_under_wine())
845 winetest_platform
= "wine";
846 winetest_platform_is_wine
= !strcmp( winetest_platform
, "wine" );
848 if (GetEnvironmentVariableA( "WINETEST_COLOR", p
, sizeof(p
) ))
850 BOOL automode
= !strcmp(p
, "auto");
851 winetest_color
= automode
? isatty( fileno( stdout
) ) : atoi(p
);
852 /* enable ANSI support for Windows console */
855 HANDLE hOutput
= (HANDLE
)_get_osfhandle( fileno( stdout
) );
857 if (GetConsoleMode( hOutput
, &mode
) &&
858 !SetConsoleMode( hOutput
, mode
| ENABLE_PROCESSED_OUTPUT
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
) &&
863 if (GetEnvironmentVariableA( "WINETEST_DEBUG", p
, sizeof(p
) )) winetest_debug
= atoi(p
);
864 if (GetEnvironmentVariableA( "WINETEST_INTERACTIVE", p
, sizeof(p
) )) winetest_interactive
= atoi(p
);
865 if (GetEnvironmentVariableA( "WINETEST_REPORT_FLAKY", p
, sizeof(p
) )) winetest_report_flaky
= atoi(p
);
866 if (GetEnvironmentVariableA( "WINETEST_REPORT_SUCCESS", p
, sizeof(p
) )) winetest_report_success
= atoi(p
);
867 if (GetEnvironmentVariableA( "WINETEST_TIME", p
, sizeof(p
) )) winetest_time
= atoi(p
);
868 winetest_last_time
= winetest_start_time
= winetest_get_time();
870 if (!strcmp( winetest_platform
, "windows" )) SetUnhandledExceptionFilter( exc_filter
);
871 if (!winetest_interactive
) SetErrorMode( SEM_FAILCRITICALERRORS
| SEM_NOGPFAULTERRORBOX
);
875 if (winetest_testlist
[0].name
&& !winetest_testlist
[1].name
) /* only one test */
876 return run_test( winetest_testlist
[0].name
);
879 if (!strcmp( argv
[1], "--list" ))
884 return run_test(argv
[1]);
887 #endif /* STANDALONE */
889 #endif /* __WINE_WINE_TEST_H */