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