Reactos
at master 1048 lines 32 kB view raw
1/* 2 * Definitions for Wine C unit tests. 3 * 4 * Copyright (C) 2002 Alexandre Julliard 5 * 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. 10 * 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. 15 * 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 19 */ 20 21#ifndef __WINE_WINE_TEST_H 22#define __WINE_WINE_TEST_H 23 24#include <stdarg.h> 25#include <stdlib.h> 26#include <windef.h> 27#include <winbase.h> 28#include <stdio.h> // In the future: replace by <wine/debug.h> 29 30#ifdef __WINE_CONFIG_H 31#error config.h should not be used in Wine tests 32#endif 33#ifdef __WINE_WINE_LIBRARY_H 34#error wine/library.h should not be used in Wine tests 35#endif 36#ifdef __WINE_WINE_UNICODE_H 37#error wine/unicode.h should not be used in Wine tests 38#endif 39#ifdef __WINE_WINE_DEBUG_H 40#error wine/debug.h should not be used in Wine tests 41#endif 42 43#ifdef __cplusplus 44extern "C" { 45#endif 46 47#ifndef INVALID_FILE_ATTRIBUTES 48#define INVALID_FILE_ATTRIBUTES (~0u) 49#endif 50#ifndef INVALID_SET_FILE_POINTER 51#define INVALID_SET_FILE_POINTER (~0u) 52#endif 53 54/* debug level */ 55extern int winetest_debug; 56 57extern int report_success; 58 59/* running in interactive mode? */ 60extern int winetest_interactive; 61 62/* current platform */ 63extern const char *winetest_platform; 64 65extern void winetest_set_location( const char* file, int line ); 66extern void winetest_subtest(const char* name); 67extern void winetest_start_todo( int is_todo ); 68extern int winetest_loop_todo(void); 69extern void winetest_end_todo(void); 70extern void winetest_start_nocount(unsigned int flags); 71extern int winetest_loop_nocount(void); 72extern void winetest_end_nocount(void); 73extern int winetest_get_mainargs( char*** pargv ); 74extern LONG winetest_get_failures(void); 75extern LONG winetest_get_successes(void); 76extern void winetest_add_failures( LONG new_failures ); 77extern void winetest_wait_child_process( HANDLE process ); 78extern void winetest_ignore_exceptions( BOOL ignore ); 79 80extern const char *wine_dbgstr_wn( const WCHAR *str, intptr_t n ); 81extern const char *wine_dbgstr_an( const CHAR *str, intptr_t n ); 82extern const char *wine_dbgstr_guid( const GUID *guid ); 83extern const char *wine_dbgstr_point( const POINT *guid ); 84extern const char *wine_dbgstr_size( const SIZE *guid ); 85extern const char *wine_dbgstr_rect( const RECT *rect ); 86#ifdef WINETEST_USE_DBGSTR_LONGLONG 87extern const char *wine_dbgstr_longlong( ULONGLONG ll ); 88#endif 89static inline const char *debugstr_a( const char *s ) { return wine_dbgstr_an( s, -1 ); } 90static inline const char *debugstr_an( const CHAR *s, intptr_t n ) { return wine_dbgstr_an( s, n ); } 91static inline const char *debugstr_w( const WCHAR *s ) { return wine_dbgstr_wn( s, -1 ); } 92static inline const char *debugstr_wn( const WCHAR *s, int n ) { return wine_dbgstr_wn( s, n ); } 93static inline const char *debugstr_guid( const struct _GUID *id ) { return wine_dbgstr_guid(id); } 94static inline const char *wine_dbgstr_a( const char *s ) { return wine_dbgstr_an( s, -1 ); } 95static inline const char *wine_dbgstr_w( const WCHAR *s ) { return wine_dbgstr_wn( s, -1 ); } 96 97/* strcmpW is available for tests compiled under Wine, but not in standalone 98 * builds under Windows, so we reimplement it under a different name. */ 99static inline int winetest_strcmpW( const WCHAR *str1, const WCHAR *str2 ) 100{ 101 while (*str1 && (*str1 == *str2)) { str1++; str2++; } 102 return *str1 - *str2; 103} 104 105#ifdef __REACTOS__ 106/* ReactOS specific extensions, useful for patches */ 107#define KUSER_SHARED_DATA_UMPTR 0x7FFE0000 108#define GetMajorNTVersion() (*(ULONG*)(KUSER_SHARED_DATA_UMPTR + 0x026C)) 109#define GetMinorNTVersion() (*(ULONG*)(KUSER_SHARED_DATA_UMPTR + 0x0270)) 110#define GetNTVersion() ((GetMajorNTVersion() << 8) | GetMinorNTVersion()) 111#endif 112 113#ifdef STANDALONE 114 115#define START_TEST(name) \ 116 static void func_##name(void); \ 117 const struct test winetest_testlist[] = { { #name, func_##name }, { 0, 0 } }; \ 118 static void func_##name(void) 119 120#else /* STANDALONE */ 121 122#ifdef __cplusplus 123#define START_TEST(name) extern "C" void func_##name(void) 124#else 125#define START_TEST(name) void func_##name(void) 126#endif 127 128#endif /* STANDALONE */ 129 130#if defined(__x86_64__) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT) 131#define __winetest_cdecl __cdecl 132#define __winetest_va_list __builtin_ms_va_list 133#else 134#define __winetest_cdecl 135#define __winetest_va_list va_list 136#endif 137 138extern int broken( int condition ); 139extern int winetest_vok( int condition, const char *msg, __winetest_va_list ap ); 140extern void winetest_vskip( const char *msg, __winetest_va_list ap ); 141 142#ifdef __GNUC__ 143# define __WINE_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args))) 144extern void __winetest_cdecl winetest_ok( int condition, const char *msg, ... ) __attribute__((format (printf,2,3) )); 145extern void __winetest_cdecl winetest_skip( const char *msg, ... ) __attribute__((format (printf,1,2))); 146extern void __winetest_cdecl winetest_win_skip( const char *msg, ... ) __attribute__((format (printf,1,2))); 147extern void __winetest_cdecl winetest_trace( const char *msg, ... ) __attribute__((format (printf,1,2))); 148extern void __winetest_cdecl winetest_print(const char* msg, ...) __attribute__((format(printf, 1, 2))); 149extern void __winetest_cdecl winetest_push_context( const char *fmt, ... ) __attribute__((format(printf, 1, 2))); 150extern void winetest_pop_context(void); 151 152#else /* __GNUC__ */ 153# define __WINE_PRINTF_ATTR(fmt,args) 154extern void __winetest_cdecl winetest_ok( int condition, const char *msg, ... ); 155extern void __winetest_cdecl winetest_skip( const char *msg, ... ); 156extern void __winetest_cdecl winetest_win_skip( const char *msg, ... ); 157extern void __winetest_cdecl winetest_trace( const char *msg, ... ); 158extern void __winetest_cdecl winetest_print(const char* msg, ...); 159extern void __winetest_cdecl winetest_push_context( const char *fmt, ... ); 160extern void winetest_pop_context(void); 161 162#endif /* __GNUC__ */ 163 164#define subtest_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_subtest 165#define ok_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ok 166#define skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_skip 167#define win_skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_win_skip 168#define trace_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_trace 169#define wait_child_process_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_wait_child_process 170#define ignore_exceptions_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ignore_exceptions 171 172#define subtest subtest_(__FILE__, __LINE__) 173#define ok ok_(__FILE__, __LINE__) 174#define skip skip_(__FILE__, __LINE__) 175#define win_skip win_skip_(__FILE__, __LINE__) 176#define trace trace_(__FILE__, __LINE__) 177#define wait_child_process wait_child_process_(__FILE__, __LINE__) 178#define ignore_exceptions ignore_exceptions_(__FILE__, __LINE__) 179 180#define todo_if(is_todo) for (winetest_start_todo(is_todo); \ 181 winetest_loop_todo(); \ 182 winetest_end_todo()) 183 184#define todo_ros todo_if(!strcmp(winetest_platform, "reactos")) 185#define todo_ros_if(is_todo) todo_if((is_todo) && !strcmp(winetest_platform, "reactos")) 186#ifdef USE_WINE_TODOS 187#define todo_wine todo_ros 188#define todo_wine_if todo_ros_if 189#else 190#define todo_wine todo_if(!strcmp(winetest_platform, "wine")) 191#define todo_wine_if(is_todo) todo_if((is_todo) && !strcmp(winetest_platform, "wine")) 192#endif 193 194#define ros_skip_flaky for (winetest_start_nocount(3); \ 195 winetest_loop_nocount(); \ 196 winetest_end_nocount()) 197 198#define disable_success_count for (winetest_start_nocount(1); \ 199 winetest_loop_nocount(); \ 200 winetest_end_nocount()) 201 202#define skip_2k3_crash if (_winver < 0x600) skip("Test skipped, because it crashes on win 2003\n"); else 203#define skip_2k3_fail if (_winver < 0x600) skip("Test skipped, because it fails on win 2003\n"); else 204 205#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 206 207#ifdef NONAMELESSUNION 208# define U(x) (x).u 209# define U1(x) (x).u1 210# define U2(x) (x).u2 211# define U3(x) (x).u3 212# define U4(x) (x).u4 213# define U5(x) (x).u5 214# define U6(x) (x).u6 215# define U7(x) (x).u7 216# define U8(x) (x).u8 217#else 218# define U(x) (x) 219# define U1(x) (x) 220# define U2(x) (x) 221# define U3(x) (x) 222# define U4(x) (x) 223# define U5(x) (x) 224# define U6(x) (x) 225# define U7(x) (x) 226# define U8(x) (x) 227#endif 228 229#ifdef NONAMELESSSTRUCT 230# define S(x) (x).s 231# define S1(x) (x).s1 232# define S2(x) (x).s2 233# define S3(x) (x).s3 234# define S4(x) (x).s4 235# define S5(x) (x).s5 236#else 237# define S(x) (x) 238# define S1(x) (x) 239# define S2(x) (x) 240# define S3(x) (x) 241# define S4(x) (x) 242# define S5(x) (x) 243#endif 244 245 246/************************************************************************/ 247/* Below is the implementation of the various functions, to be included 248 * directly into the generated testlist.c file. 249 * It is done that way so that the dlls can build the test routines with 250 * different includes or flags if needed. 251 */ 252 253#ifdef STANDALONE 254 255#include <stdio.h> 256 257#if defined(__x86_64__) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT) 258# define __winetest_va_start(list,arg) __builtin_ms_va_start(list,arg) 259# define __winetest_va_end(list) __builtin_ms_va_end(list) 260#else 261# define __winetest_va_start(list,arg) va_start(list,arg) 262# define __winetest_va_end(list) va_end(list) 263#endif 264 265/* Define WINETEST_MSVC_IDE_FORMATTING to alter the output format winetest will use for file/line numbers. 266 This alternate format makes the file/line numbers clickable in visual studio, to directly jump to them. */ 267#if defined(WINETEST_MSVC_IDE_FORMATTING) 268# define __winetest_file_line_prefix "%s(%d)" 269#else 270# define __winetest_file_line_prefix "%s:%d" 271#endif 272 273struct test 274{ 275 const char *name; 276 void (*func)(void); 277}; 278 279extern const struct test winetest_testlist[]; 280 281/* debug level */ 282int winetest_debug = 1; 283 284/* interactive mode? */ 285int winetest_interactive = 0; 286 287/* current platform */ 288const char *winetest_platform = "windows"; 289 290/* report successful tests (BOOL) */ 291int report_success = 0; 292 293/* passing arguments around */ 294static int winetest_argc; 295static char** winetest_argv; 296 297static const struct test *current_test; /* test currently being run */ 298 299static LONG successes; /* number of successful tests */ 300static LONG failures; /* number of failures */ 301static LONG skipped; /* number of skipped test chunks */ 302static LONG todo_successes; /* number of successful tests inside todo block */ 303static LONG todo_failures; /* number of failures inside todo block */ 304 305/* The following data must be kept track of on a per-thread basis */ 306typedef struct 307{ 308 const char* current_file; /* file of current check */ 309 int current_line; /* line of current check */ 310 unsigned int todo_level; /* current todo nesting level */ 311 unsigned int nocount_level; 312 int todo_do_loop; 313 char *str_pos; /* position in debug buffer */ 314 char strings[2000]; /* buffer for debug strings */ 315 char context[8][128]; /* data to print before messages */ 316 unsigned int context_count; /* number of context prefixes */ 317} tls_data; 318static DWORD tls_index; 319 320static tls_data* get_tls_data(void) 321{ 322 tls_data* data; 323 DWORD last_error; 324 325 last_error=GetLastError(); 326 data=(tls_data*)TlsGetValue(tls_index); 327 if (!data) 328 { 329 data=(tls_data*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(tls_data)); 330 data->str_pos = data->strings; 331 TlsSetValue(tls_index,data); 332 } 333 SetLastError(last_error); 334 return data; 335} 336 337/* allocate some tmp space for a string */ 338static char *get_temp_buffer( size_t n ) 339{ 340 tls_data *data = get_tls_data(); 341 char *res = data->str_pos; 342 343 if (res + n >= &data->strings[sizeof(data->strings)]) res = data->strings; 344 data->str_pos = res + n; 345 return res; 346} 347 348/* release extra space that we requested in gimme1() */ 349static void release_temp_buffer( char *ptr, size_t size ) 350{ 351 tls_data *data = get_tls_data(); 352 data->str_pos = ptr + size; 353} 354 355static void exit_process( int code ) 356{ 357 fflush( stdout ); 358 ExitProcess( code ); 359} 360 361 362void winetest_set_location( const char* file, int line ) 363{ 364 tls_data* data=get_tls_data(); 365#if defined(WINETEST_MSVC_IDE_FORMATTING) 366 data->current_file = file; 367#else 368 data->current_file=strrchr(file,'/'); 369 if (data->current_file==NULL) 370 data->current_file=strrchr(file,'\\'); 371 if (data->current_file==NULL) 372 data->current_file=file; 373 else 374 data->current_file++; 375#endif 376 data->current_line=line; 377} 378 379#ifdef __GNUC__ 380static void __winetest_cdecl winetest_printf( const char *msg, ... ) __attribute__((format(printf,1,2))); 381#else 382static void __winetest_cdecl winetest_printf(const char* msg, ...); 383#endif 384static void __winetest_cdecl winetest_printf( const char *msg, ... ) 385{ 386 tls_data *data = get_tls_data(); 387 __winetest_va_list valist; 388 389 fprintf( stdout, __winetest_file_line_prefix ": ", data->current_file, data->current_line ); 390 __winetest_va_start( valist, msg ); 391 vfprintf( stdout, msg, valist ); 392 __winetest_va_end( valist ); 393} 394 395static void __winetest_cdecl winetest_vprintf(const char* msg, __winetest_va_list valist); 396static void __winetest_cdecl winetest_vprintf(const char *msg, __winetest_va_list valist) 397{ 398 tls_data *data = get_tls_data(); 399 400 fprintf(stdout, __winetest_file_line_prefix ": ", data->current_file, data->current_line); 401 vfprintf(stdout, msg, valist); 402} 403 404static void winetest_print_location( const char *msg, ... ) 405{ 406 tls_data *data = get_tls_data(); 407 va_list valist; 408 409 winetest_printf( "%s:%d ", data->current_file, data->current_line ); 410 va_start( valist, msg ); 411 winetest_vprintf( msg, valist ); 412 va_end( valist ); 413} 414 415static void __winetest_cdecl winetest_print_context( const char *msgtype ) 416{ 417 tls_data *data = get_tls_data(); 418 unsigned int i; 419 420 winetest_printf( "%s", msgtype ); 421 for (i = 0; i < data->context_count; ++i) 422 fprintf( stdout, "%s: ", data->context[i] ); 423} 424 425void winetest_subtest(const char* name) 426{ 427 tls_data* data = get_tls_data(); 428 fprintf(stdout, __winetest_file_line_prefix ": Subtest %s\n", 429 data->current_file, data->current_line, name); 430} 431 432void winetest_ignore_exceptions( BOOL ignore ) 433{ 434 winetest_print_location( "IgnoreExceptions=%d\n", ignore ? 1 : 0 ); 435} 436 437int broken( int condition ) 438{ 439 return ((strcmp(winetest_platform, "windows") == 0) 440#ifndef USE_WINE_TODOS 441 || (strcmp(winetest_platform, "reactos") == 0) 442#endif 443 ) && condition; 444} 445 446/* 447 * Checks condition. 448 * Parameters: 449 * - condition - condition to check; 450 * - msg test description; 451 * - file - test application source code file name of the check 452 * - line - test application source code file line number of the check 453 * Return: 454 * 0 if condition does not have the expected value, 1 otherwise 455 */ 456int winetest_vok( int condition, const char *msg, __winetest_va_list args ) 457{ 458 tls_data* data=get_tls_data(); 459 460 if (data->todo_level) 461 { 462 if (condition) 463 { 464 winetest_print_context( "Test succeeded inside todo block: " ); 465 vfprintf(stdout, msg, args); 466 if ((data->nocount_level & 2) == 0) 467 InterlockedIncrement(&todo_failures); 468 return 0; 469 } 470 else 471 { 472 /* show todos even if traces are disabled*/ 473 /*if (winetest_debug > 0)*/ 474 { 475 winetest_print_context( "Test marked todo: " ); 476 vfprintf(stdout, msg, args); 477 } 478 if ((data->nocount_level & 1) == 0) 479 InterlockedIncrement(&todo_successes); 480 return 1; 481 } 482 } 483 else 484 { 485 if (!condition) 486 { 487 winetest_print_context( "Test failed: " ); 488 vfprintf(stdout, msg, args); 489 if ((data->nocount_level & 2) == 0) 490 InterlockedIncrement(&failures); 491 return 0; 492 } 493 else 494 { 495 if (report_success && (data->nocount_level & 1) == 0) 496 { 497 winetest_printf("Test succeeded\n"); 498 } 499 if ((data->nocount_level & 1) == 0) 500 InterlockedIncrement(&successes); 501 return 1; 502 } 503 } 504} 505 506void __winetest_cdecl winetest_ok( int condition, const char *msg, ... ) 507{ 508 __winetest_va_list valist; 509 510 __winetest_va_start(valist, msg); 511 winetest_vok(condition, msg, valist); 512 __winetest_va_end(valist); 513} 514 515void __winetest_cdecl winetest_trace( const char *msg, ... ) 516{ 517 __winetest_va_list valist; 518 519 if (winetest_debug > 0) 520 { 521 winetest_print_context( "" ); 522 __winetest_va_start(valist, msg); 523 vfprintf(stdout, msg, valist); 524 __winetest_va_end(valist); 525 } 526} 527 528void __winetest_cdecl winetest_print(const char* msg, ...) 529{ 530 __winetest_va_list valist; 531 tls_data* data = get_tls_data(); 532 533 fprintf(stdout, __winetest_file_line_prefix ": ", data->current_file, data->current_line); 534 __winetest_va_start(valist, msg); 535 vfprintf(stdout, msg, valist); 536 __winetest_va_end(valist); 537} 538 539void winetest_vskip( const char *msg, __winetest_va_list args ) 540{ 541 winetest_print_context( "Tests skipped: " ); 542 vfprintf(stdout, msg, args); 543 skipped++; 544} 545 546void __winetest_cdecl winetest_skip( const char *msg, ... ) 547{ 548 __winetest_va_list valist; 549 __winetest_va_start(valist, msg); 550 winetest_vskip(msg, valist); 551 __winetest_va_end(valist); 552} 553 554void __winetest_cdecl winetest_win_skip( const char *msg, ... ) 555{ 556 __winetest_va_list valist; 557 __winetest_va_start(valist, msg); 558 if ((strcmp(winetest_platform, "windows") == 0) 559#if !defined(USE_WINE_TODOS) || defined(USE_WIN_SKIP) 560 || (strcmp(winetest_platform, "reactos") == 0) 561#endif 562 ) 563 winetest_vskip(msg, valist); 564 else 565 winetest_vok(0, msg, valist); 566 __winetest_va_end(valist); 567} 568 569void winetest_start_todo( int is_todo ) 570{ 571 tls_data* data=get_tls_data(); 572 data->todo_level = (data->todo_level << 1) | (is_todo != 0); 573 data->todo_do_loop=1; 574} 575 576int winetest_loop_todo(void) 577{ 578 tls_data* data=get_tls_data(); 579 int do_loop=data->todo_do_loop; 580 data->todo_do_loop=0; 581 return do_loop; 582} 583 584void winetest_end_todo(void) 585{ 586 tls_data* data=get_tls_data(); 587 data->todo_level >>= 1; 588} 589 590void winetest_start_nocount(unsigned int flags) 591{ 592 tls_data* data = get_tls_data(); 593 594 /* The lowest 2 bits of nocount_level specify whether counting of successes 595 and/or failures is disabled. For each nested level the bits are shifted 596 left, the new lowest 2 bits are copied from the previous state and ored 597 with the new mask. This allows nested handling of both states up tp a 598 level of 16. */ 599 flags |= data->nocount_level & 3; 600 data->nocount_level = (data->nocount_level << 2) | flags; 601 data->todo_do_loop = 1; 602} 603 604int winetest_loop_nocount(void) 605{ 606 tls_data* data = get_tls_data(); 607 int do_loop = data->todo_do_loop; 608 data->todo_do_loop = 0; 609 return do_loop; 610} 611 612void winetest_end_nocount(void) 613{ 614 tls_data* data = get_tls_data(); 615 data->nocount_level >>= 2; 616} 617 618void __winetest_cdecl winetest_push_context(const char* fmt, ...) 619{ 620 tls_data* data = get_tls_data(); 621 __winetest_va_list valist; 622 623 if (data->context_count < ARRAY_SIZE(data->context)) 624 { 625 __winetest_va_start(valist, fmt); 626 vsnprintf(data->context[data->context_count], sizeof(data->context[data->context_count]), fmt, valist); 627 __winetest_va_end(valist); 628 data->context[data->context_count][sizeof(data->context[data->context_count]) - 1] = 0; 629 } 630 ++data->context_count; 631} 632 633void winetest_pop_context(void) 634{ 635 tls_data* data = get_tls_data(); 636 637 if (data->context_count) 638 --data->context_count; 639} 640 641int winetest_get_mainargs( char*** pargv ) 642{ 643 *pargv = winetest_argv; 644 return winetest_argc; 645} 646 647LONG winetest_get_failures(void) 648{ 649 return failures; 650} 651 652LONG winetest_get_successes(void) 653{ 654 return successes; 655} 656 657void winetest_add_failures( LONG new_failures ) 658{ 659 while (new_failures-- > 0) 660 InterlockedIncrement( &failures ); 661} 662 663void winetest_wait_child_process( HANDLE process ) 664{ 665 DWORD exit_code = 1; 666 667 if (WaitForSingleObject( process, 30000 )) 668 fprintf( stdout, "%s: child process wait failed\n", current_test->name ); 669 else 670 GetExitCodeProcess( process, &exit_code ); 671 672 if (exit_code) 673 { 674 if (exit_code > 255) 675 { 676 fprintf( stdout, "%s: exception 0x%08x in child process\n", current_test->name, (unsigned)exit_code ); 677 InterlockedIncrement( &failures ); 678 } 679 else 680 { 681 fprintf( stdout, "%s: %u failures in child process\n", 682 current_test->name, (unsigned)exit_code ); 683 while (exit_code-- > 0) 684 InterlockedIncrement(&failures); 685 } 686 } 687} 688 689const char *wine_dbgstr_an( const CHAR *str, intptr_t n ) 690{ 691 char *dst, *res; 692 size_t size; 693 694 if (!((ULONG_PTR)str >> 16)) 695 { 696 if (!str) return "(null)"; 697 res = get_temp_buffer( 6 ); 698 sprintf( res, "#%04x", LOWORD(str) ); 699 return res; 700 } 701 if (n == -1) 702 { 703 const CHAR *end = str; 704 while (*end) end++; 705 n = end - str; 706 } 707 if (n < 0) n = 0; 708 size = 12 + min( 300, n * 5 ); 709 dst = res = get_temp_buffer( size ); 710 *dst++ = '"'; 711 while (n-- > 0 && dst <= res + size - 10) 712 { 713 CHAR c = *str++; 714 switch (c) 715 { 716 case '\n': *dst++ = '\\'; *dst++ = 'n'; break; 717 case '\r': *dst++ = '\\'; *dst++ = 'r'; break; 718 case '\t': *dst++ = '\\'; *dst++ = 't'; break; 719 case '"': *dst++ = '\\'; *dst++ = '"'; break; 720 case '\\': *dst++ = '\\'; *dst++ = '\\'; break; 721 default: 722 if (c >= ' ' && c <= 126) 723 *dst++ = (char)c; 724 else 725 { 726 *dst++ = '\\'; 727 sprintf(dst,"%04x",c); 728 dst+=4; 729 } 730 } 731 } 732 *dst++ = '"'; 733 if (n > 0) 734 { 735 *dst++ = '.'; 736 *dst++ = '.'; 737 *dst++ = '.'; 738 } 739 *dst++ = 0; 740 release_temp_buffer( res, dst - res ); 741 return res; 742} 743 744const char *wine_dbgstr_wn( const WCHAR *str, intptr_t n ) 745{ 746 char *res; 747 static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; 748 char buffer[300], *dst = buffer; 749 750 if (!str) return "(null)"; 751 if (!((ULONG_PTR)str >> 16)) 752 { 753 res = get_temp_buffer( 6 ); 754 sprintf( res, "#%04x", LOWORD(str) ); 755 return res; 756 } 757 if (IsBadStringPtrW(str,n)) return "(invalid)"; 758 if (n == -1) for (n = 0; str[n]; n++) ; 759 *dst++ = 'L'; 760 *dst++ = '"'; 761 while (n-- > 0 && dst <= buffer + sizeof(buffer) - 10) 762 { 763 WCHAR c = *str++; 764 switch (c) 765 { 766 case '\n': *dst++ = '\\'; *dst++ = 'n'; break; 767 case '\r': *dst++ = '\\'; *dst++ = 'r'; break; 768 case '\t': *dst++ = '\\'; *dst++ = 't'; break; 769 case '"': *dst++ = '\\'; *dst++ = '"'; break; 770 case '\\': *dst++ = '\\'; *dst++ = '\\'; break; 771 default: 772 if (c < ' ' || c >= 127) 773 { 774 *dst++ = '\\'; 775 *dst++ = hex[(c >> 12) & 0x0f]; 776 *dst++ = hex[(c >> 8) & 0x0f]; 777 *dst++ = hex[(c >> 4) & 0x0f]; 778 *dst++ = hex[c & 0x0f]; 779 } 780 else *dst++ = (char)c; 781 } 782 } 783 *dst++ = '"'; 784 if (n > 0) 785 { 786 *dst++ = '.'; 787 *dst++ = '.'; 788 *dst++ = '.'; 789 } 790 *dst = 0; 791 792 res = get_temp_buffer(strlen(buffer) + 1); 793 strcpy(res, buffer); 794 return res; 795} 796 797const char *wine_dbgstr_guid( const GUID *guid ) 798{ 799 char *res; 800 801 if (!guid) return "(null)"; 802 res = get_temp_buffer( 39 ); /* CHARS_IN_GUID */ 803 sprintf( res, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 804 (unsigned int)guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], 805 guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], 806 guid->Data4[5], guid->Data4[6], guid->Data4[7] ); 807 return res; 808} 809 810const char *wine_dbgstr_point( const POINT *point ) 811{ 812 char *res; 813 814 if (!point) return "(null)"; 815 res = get_temp_buffer( 60 ); 816#ifdef __ROS_LONG64__ 817 sprintf( res, "(%d,%d)", point->x, point->y ); 818#else 819 sprintf( res, "(%ld,%ld)", point->x, point->y ); 820#endif 821 release_temp_buffer( res, strlen(res) + 1 ); 822 return res; 823} 824 825const char *wine_dbgstr_size( const SIZE *size ) 826{ 827 char *res; 828 829 if (!size) return "(null)"; 830 res = get_temp_buffer( 60 ); 831#ifdef __ROS_LONG64__ 832 sprintf( res, "(%d,%d)", size->cx, size->cy ); 833#else 834 sprintf( res, "(%ld,%ld)", size->cx, size->cy ); 835#endif 836 release_temp_buffer( res, strlen(res) + 1 ); 837 return res; 838} 839 840const char *wine_dbgstr_rect( const RECT *rect ) 841{ 842 char *res; 843 844 if (!rect) return "(null)"; 845 res = get_temp_buffer( 60 ); 846#ifdef __ROS_LONG64__ 847 sprintf( res, "(%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom ); 848#else 849 sprintf( res, "(%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom ); 850#endif 851 release_temp_buffer( res, strlen(res) + 1 ); 852 return res; 853} 854 855#ifdef WINETEST_USE_DBGSTR_LONGLONG 856const char *wine_dbgstr_longlong( ULONGLONG ll ) 857{ 858 char *res; 859 860 res = get_temp_buffer( 20 ); 861 if (/*sizeof(ll) > sizeof(unsigned long) &&*/ ll >> 32) /* ULONGLONG is always > long in ReactOS */ 862 sprintf( res, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll ); 863 else 864 sprintf( res, "%lx", (unsigned long)ll ); 865 release_temp_buffer( res, strlen(res) + 1 ); 866 return res; 867} 868#endif 869 870/* Find a test by name */ 871static const struct test *find_test( const char *name ) 872{ 873 const struct test *test; 874 const char *p; 875 size_t len; 876 877 if ((p = strrchr( name, '/' ))) name = p + 1; 878 if ((p = strrchr( name, '\\' ))) name = p + 1; 879 len = strlen(name); 880 if (len > 2 && !strcmp( name + len - 2, ".c" )) len -= 2; 881 882 for (test = winetest_testlist; test->name; test++) 883 { 884 if (!strncmp( test->name, name, len ) && !test->name[len]) break; 885 } 886 return test->name ? test : NULL; 887} 888 889 890/* Display list of valid tests */ 891static void list_tests(void) 892{ 893 const struct test *test; 894 895 fprintf( stdout, "Valid test names:\n" ); 896 for (test = winetest_testlist; test->name; test++) fprintf( stdout, " %s\n", test->name ); 897} 898 899/* Disable false-positive claiming "test" would be NULL-dereferenced */ 900#if defined(_MSC_VER) 901#pragma warning(push) 902#pragma warning(disable:28182) 903#endif 904 905/* Run a named test, and return exit status */ 906static int run_test( const char *name ) 907{ 908 const struct test *test; 909 int status; 910 911 if (!(test = find_test( name ))) 912 { 913 fprintf( stdout, "Fatal: test '%s' does not exist.\n", name ); 914 exit_process(1); 915 } 916 successes = failures = todo_successes = todo_failures = 0; 917 tls_index=TlsAlloc(); 918 current_test = test; 919 test->func(); 920 921 /* show test results even if traces are disabled */ 922 /*if (winetest_debug)*/ 923 { 924 fprintf( stdout, "\n%s: %d tests executed (%d marked as todo, %d %s), %d skipped.\n", 925 test->name, (int)(successes + failures + todo_successes + todo_failures), 926 (int)todo_successes, (int)(failures + todo_failures), 927 (failures + todo_failures != 1) ? "failures" : "failure", 928 (int)skipped ); 929 } 930 status = (failures + todo_failures < 255) ? failures + todo_failures : 255; 931 return status; 932} 933 934#if defined(_MSC_VER) 935#pragma warning(pop) 936#endif 937 938/* Display usage and exit */ 939static void usage( const char *argv0 ) 940{ 941 fprintf( stdout, "Usage: %s test_name\n\n", argv0 ); 942 list_tests(); 943 exit_process(1); 944} 945 946 947/* main function */ 948int main( int argc, char **argv ) 949{ 950 char p[128]; 951 952 setvbuf (stdout, NULL, _IONBF, 0); 953 954 winetest_argc = argc; 955 winetest_argv = argv; 956 957 if (GetEnvironmentVariableA( "WINETEST_PLATFORM", p, sizeof(p) )) winetest_platform = _strdup(p); 958 if (GetEnvironmentVariableA( "WINETEST_DEBUG", p, sizeof(p) )) winetest_debug = atoi(p); 959 if (GetEnvironmentVariableA( "WINETEST_INTERACTIVE", p, sizeof(p) )) winetest_interactive = atoi(p); 960 if (GetEnvironmentVariableA( "WINETEST_REPORT_SUCCESS", p, sizeof(p) )) report_success = atoi(p); 961 962 if (!winetest_interactive) SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX ); 963 964 if (!argv[1]) 965 { 966 if (winetest_testlist[0].name && !winetest_testlist[1].name) /* only one test */ 967 return run_test( winetest_testlist[0].name ); 968 usage( argv[0] ); 969 } 970 if (!strcmp( argv[1], "--list" )) 971 { 972 list_tests(); 973 return 0; 974 } 975 return run_test(argv[1]); 976} 977 978#endif /* STANDALONE */ 979 980// hack for ntdll winetest (this is defined in excpt.h) 981#undef exception_info 982 983// Some helpful definitions 984 985#define ok_hex_(file, line, expression, result) \ 986 do { \ 987 int _value = (expression); \ 988 int _result = (result); \ 989 ok_(file, line)(_value == _result, "Wrong value for '%s', expected: " #result " (0x%x), got: 0x%x\n", \ 990 #expression, _result, _value); \ 991 } while (0) 992#define ok_hex(expression, result) ok_hex_(__FILE__, __LINE__, expression, result) 993 994#define ok_dec_(file, line, expression, result) \ 995 do { \ 996 int _value = (expression); \ 997 int _result = (result); \ 998 ok_(file, line)(_value == _result, "Wrong value for '%s', expected: " #result " (%d), got: %d\n", \ 999 #expression, _result, _value); \ 1000 } while (0) 1001#define ok_dec(expression, result) ok_dec_(__FILE__, __LINE__, expression, result) 1002 1003#define ok_ptr_(file, line, expression, result) \ 1004 do { \ 1005 const void *_value = (expression); \ 1006 const void *_result = (result); \ 1007 ok_(file, line)(_value == _result, "Wrong value for '%s', expected: " #result " (%p), got: %p\n", \ 1008 #expression, _result, _value); \ 1009 } while (0) 1010#define ok_ptr(expression, result) ok_ptr_(__FILE__, __LINE__, expression, result) 1011 1012#define ok_size_t_(file, line, expression, result) \ 1013 do { \ 1014 size_t _value = (expression); \ 1015 size_t _result = (result); \ 1016 ok_(file, line)(_value == _result, "Wrong value for '%s', expected: " #result " (%Ix), got: %Ix\n", \ 1017 #expression, _result, _value); \ 1018 } while (0) 1019#define ok_size_t(expression, result) ok_size_t_(__FILE__, __LINE__, expression, result) 1020 1021#define ok_char(expression, result) ok_hex(expression, result) 1022 1023#define ok_err_(file, line, error) \ 1024 ok_(file, line)(GetLastError() == (error), "Wrong last error. Expected " #error ", got 0x%lx\n", GetLastError()) 1025#define ok_err(error) ok_err_(__FILE__, __LINE__, error) 1026 1027#define ok_str_(file, line, x, y) \ 1028 ok_(file, line)(strcmp(x, y) == 0, "Wrong string. Expected '%s', got '%s'\n", y, x) 1029#define ok_str(x, y) ok_str_(__FILE__, __LINE__, x, y) 1030 1031#define ok_wstr_(file, line, x, y) \ 1032 ok_(file, line)(wcscmp(x, y) == 0, "Wrong string. Expected '%S', got '%S'\n", y, x) 1033#define ok_wstr(x, y) ok_wstr_(__FILE__, __LINE__, x, y) 1034 1035#define ok_long(expression, result) ok_hex(expression, result) 1036#define ok_int(expression, result) ok_dec(expression, result) 1037#define ok_int_(file, line, expression, result) ok_dec_(file, line, expression, result) 1038#define ok_ntstatus(status, expected) ok_hex(status, expected) 1039#define ok_hdl ok_ptr 1040 1041#define is_reactos() \ 1042 (*(unsigned*)((size_t)0x7FFE0FFC) == 0x8EAC705) 1043 1044#ifdef __cplusplus 1045} /* extern "C" */ 1046#endif 1047 1048#endif /* __WINE_WINE_TEST_H */