include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / include / wine / test.h
blob8f3f3bb0d50c273f4f74fe6768cc33186cc8df9f
1 /*
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
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <io.h>
27 #include <windef.h>
28 #include <winbase.h>
29 #include <wine/debug.h>
31 #ifndef INVALID_FILE_ATTRIBUTES
32 #define INVALID_FILE_ATTRIBUTES (~0u)
33 #endif
34 #ifndef INVALID_SET_FILE_POINTER
35 #define INVALID_SET_FILE_POINTER (~0u)
36 #endif
38 /* debug level */
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 */
80 int flaky_do_loop;
81 unsigned int todo_level; /* current todo nesting level */
82 int todo_do_loop;
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 );
98 #ifdef STANDALONE
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)
103 #else
104 #define START_TEST(name) void func_##name(void)
105 #endif
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
115 #else
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
123 #endif
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(); \
142 winetest_end_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)
147 #ifndef ARRAY_SIZE
148 # define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
149 #endif
151 /* Records the location of the next check.
152 * See the xxx_(file, line) macros.
154 * Parameters:
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;
166 else
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, ... )
183 va_list valist;
184 int ret;
186 va_start( valist, msg );
187 ret = winetest_vprintf( msg, valist );
188 va_end( valist );
190 return ret;
193 static const char *winetest_elapsed( char *buffer )
195 int now;
197 if (!winetest_time) return "";
198 winetest_last_time = now = winetest_get_time();
199 sprintf( buffer, "%.3f", (now - winetest_start_time) / 1000.0 );
200 return buffer;
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();
207 char elapsed[64];
208 va_list valist;
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 );
213 va_end( valist );
216 static void winetest_print_context( const char *msgtype )
218 struct winetest_thread_data *data = winetest_get_thread_data();
219 unsigned int i;
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;
251 int index, count;
253 if (winetest_debug > 1)
254 return 0;
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();
266 return count;
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.
273 * Parameters:
274 * - condition - true if the check succeeded, false otherwise;
275 * - msg - failure message format;
276 * - args - arguments for the failure message
277 * Return:
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)
286 if (condition)
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 );
296 else
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();
305 return 0;
307 else
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 );
324 return 1;
327 else
329 if (!condition)
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 );
339 else
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();
348 return 0;
350 else
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 );
362 return 1;
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, ... )
370 va_list valist;
372 va_start(valist, msg);
373 winetest_vok(condition, msg, valist);
374 va_end(valist);
377 static void winetest_trace( const char *msg, ... ) __WINE_PRINTF_ATTR(1,2);
378 static inline void winetest_trace( const char *msg, ... )
380 va_list valist;
382 if (!winetest_debug)
383 return;
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 );
390 va_end(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.
415 * Parameters:
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, ... )
422 va_list valist;
423 va_start(valist, msg);
424 winetest_vskip(msg, valist);
425 va_end(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, ... )
431 va_list valist;
432 va_start(valist, msg);
433 if (!winetest_platform_is_wine)
434 winetest_vskip(msg, valist);
435 else
436 winetest_vok(0, msg, valist);
437 va_end(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.
444 * Remarks:
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;
464 return do_flaky;
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.
476 * Remarks:
477 * - is_todo should never be true on Windows. To ensure this, always use
478 * todo_wine_if().
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;
492 return do_loop;
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.
504 * Parameters:
505 * - msg - failure message format;
506 * - args - arguments for the failure message
508 * Remarks:
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
513 * context.
515 * Example:
517 * for (i = 0; i < ARRAY_SIZE(test_parameters); i++)
519 * winetest_push_context("%d", i);
520 * ...
521 * ok(WinAPI(test_parameters[i]), ...);
522 * ...
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();
530 va_list valist;
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 );
536 va_end(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.
568 #ifdef STANDALONE
570 #include <stdio.h>
571 #include <excpt.h>
573 struct test
575 const char *name;
576 void (*func)(void);
579 extern const struct test winetest_testlist[];
581 /* debug level */
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;
630 DWORD last_error;
632 last_error = GetLastError();
633 data = TlsGetValue( tls_index );
634 if (!data)
636 data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) );
637 data->str_pos = data->strings;
638 TlsSetValue( tls_index, data );
640 SetLastError( last_error );
641 return data;
644 static void exit_process( int code )
646 fflush( stdout );
647 ExitProcess( code );
650 void winetest_print_lock(void)
652 UINT ret;
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 );
659 winetest_mutex = 0;
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 )
686 DWORD ret;
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() );
697 else
699 DWORD exit_code;
700 GetExitCodeProcess( process, &exit_code );
701 if (exit_code > 255)
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 );
711 else if (exit_code)
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;
725 const char *p;
726 size_t len;
728 if ((p = strrchr( name, '/' ))) name = p + 1;
729 if ((p = strrchr( name, '\\' ))) name = p + 1;
730 len = strlen(name);
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;
756 int status;
758 if (!(test = find_test( name )))
760 printf( "Fatal: test '%s' does not exist.\n", name );
761 exit_process(1);
763 tls_index=TlsAlloc();
764 current_test = test;
765 test->func();
767 if (winetest_debug)
769 char elapsed[64];
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;
787 return status;
791 /* Display usage and exit */
792 static void usage( const char *argv0 )
794 printf( "Usage: %s test_name\n\n", argv0 );
795 list_tests();
796 exit_process(1);
799 /* trap unhandled exceptions */
800 static LONG CALLBACK exc_filter( EXCEPTION_POINTERS *ptrs )
802 struct winetest_thread_data *data = winetest_get_thread_data();
803 char elapsed[64];
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 );
814 fflush( stdout );
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);
827 #ifdef __GNUC__
828 void _fpreset(void) {} /* override the mingw fpu init code */
829 #endif
831 /* main function */
832 int main( int argc, char **argv )
834 char p[128];
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 */
853 if (winetest_color)
855 HANDLE hOutput = (HANDLE)_get_osfhandle( fileno( stdout ) );
856 DWORD mode;
857 if (GetConsoleMode( hOutput, &mode ) &&
858 !SetConsoleMode( hOutput, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING ) &&
859 automode)
860 winetest_color = 0;
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 );
873 if (!argv[1])
875 if (winetest_testlist[0].name && !winetest_testlist[1].name) /* only one test */
876 return run_test( winetest_testlist[0].name );
877 usage( argv[0] );
879 if (!strcmp( argv[1], "--list" ))
881 list_tests();
882 return 0;
884 return run_test(argv[1]);
887 #endif /* STANDALONE */
889 #endif /* __WINE_WINE_TEST_H */