1/* 2 * Copyright 2008 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#include <setjmp.h> 17#ifndef _WIN32 18#include <signal.h> 19#endif // !_WIN32 20#include <stdarg.h> 21#include <stddef.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#ifdef _WIN32 26#include <windows.h> 27#endif // _WIN32 28#include <cmockery.h> 29 30#ifdef _WIN32 31#define vsnprintf _vsnprintf 32#endif // _WIN32 33 34// Size of guard bytes around dynamically allocated blocks. 35#define MALLOC_GUARD_SIZE 16 36// Pattern used to initialize guard blocks. 37#define MALLOC_GUARD_PATTERN 0xEF 38// Pattern used to initialize memory allocated with test_malloc(). 39#define MALLOC_ALLOC_PATTERN 0xBA 40#define MALLOC_FREE_PATTERN 0xCD 41// Alignment of allocated blocks. NOTE: This must be base2. 42#define MALLOC_ALIGNMENT sizeof(size_t) 43 44// Printf formatting for source code locations. 45#define SOURCE_LOCATION_FORMAT "%s:%d" 46 47// Calculates the number of elements in an array. 48#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) 49 50// Doubly linked list node. 51typedef struct ListNode { 52 const void *value; 53 int refcount; 54 struct ListNode *next; 55 struct ListNode *prev; 56} ListNode; 57 58// Debug information for malloc(). 59typedef struct MallocBlockInfo { 60 void* block; // Address of the block returned by malloc(). 61 size_t allocated_size; // Total size of the allocated block. 62 size_t size; // Request block size. 63 SourceLocation location; // Where the block was allocated. 64 ListNode node; // Node within list of all allocated blocks. 65} MallocBlockInfo; 66 67// State of each test. 68typedef struct TestState { 69 const ListNode *check_point; // Check point of the test if there's a 70 // setup function. 71 void *state; // State associated with the test. 72} TestState; 73 74// Determines whether two values are the same. 75typedef int (*EqualityFunction)(const void *left, const void *right); 76 77// Value of a symbol and the place it was declared. 78typedef struct SymbolValue { 79 SourceLocation location; 80 const void* value; 81} SymbolValue; 82 83/* Contains a list of values for a symbol. 84 * NOTE: Each structure referenced by symbol_values_list_head must have a 85 * SourceLocation as its' first member. 86 */ 87typedef struct SymbolMapValue { 88 const char *symbol_name; 89 ListNode symbol_values_list_head; 90} SymbolMapValue; 91 92// Used by list_free() to deallocate values referenced by list nodes. 93typedef void (*CleanupListValue)(const void *value, void *cleanup_value_data); 94 95// Structure used to check the range of integer types. 96typedef struct CheckIntegerRange { 97 CheckParameterEvent event; 98 int minimum; 99 int maximum; 100} CheckIntegerRange; 101 102// Structure used to check whether an integer value is in a set. 103typedef struct CheckIntegerSet { 104 CheckParameterEvent event; 105 const void **set; 106 size_t size_of_set; 107} CheckIntegerSet; 108 109/* Used to check whether a parameter matches the area of memory referenced by 110 * this structure. */ 111typedef struct CheckMemoryData { 112 CheckParameterEvent event; 113 const void *memory; 114 size_t size; 115} CheckMemoryData; 116 117static ListNode* list_initialize(ListNode * const node); 118static ListNode* list_add(ListNode * const head, ListNode *new_node); 119static ListNode* list_add_value(ListNode * const head, const void *value, 120 const int count); 121static ListNode* list_remove( 122 ListNode * const node, const CleanupListValue cleanup_value, 123 void * const cleanup_value_data); 124static void list_remove_free( 125 ListNode * const node, const CleanupListValue cleanup_value, 126 void * const cleanup_value_data); 127static int list_empty(const ListNode * const head); 128static int list_find( 129 ListNode * const head, const void *value, 130 const EqualityFunction equal_func, ListNode **output); 131static int list_first(ListNode * const head, ListNode **output); 132static ListNode* list_free( 133 ListNode * const head, const CleanupListValue cleanup_value, 134 void * const cleanup_value_data); 135 136static void add_symbol_value( 137 ListNode * const symbol_map_head, const char * const symbol_names[], 138 const size_t number_of_symbol_names, const void* value, const int count); 139static int get_symbol_value( 140 ListNode * const symbol_map_head, const char * const symbol_names[], 141 const size_t number_of_symbol_names, void **output); 142static void free_value(const void *value, void *cleanup_value_data); 143static void free_symbol_map_value( 144 const void *value, void *cleanup_value_data); 145static void remove_always_return_values(ListNode * const map_head, 146 const size_t number_of_symbol_names); 147static int check_for_leftover_values( 148 const ListNode * const map_head, const char * const error_message, 149 const size_t number_of_symbol_names); 150// This must be called at the beginning of a test to initialize some data 151// structures. 152static void initialize_testing(const char *test_name); 153// This must be called at the end of a test to free() allocated structures. 154static void teardown_testing(const char *test_name); 155 156 157// Keeps track of the calling context returned by setenv() so that the fail() 158// method can jump out of a test. 159static jmp_buf global_run_test_env; 160static int global_running_test = 0; 161 162// Keeps track of the calling context returned by setenv() so that 163// mock_assert() can optionally jump back to expect_assert_failure(). 164jmp_buf global_expect_assert_env; 165int global_expecting_assert = 0; 166 167// Keeps a map of the values that functions will have to return to provide 168// mocked interfaces. 169static ListNode global_function_result_map_head; 170// Location of the last mock value returned was declared. 171static SourceLocation global_last_mock_value_location; 172 173/* Keeps a map of the values that functions expect as parameters to their 174 * mocked interfaces. */ 175static ListNode global_function_parameter_map_head; 176// Location of last parameter value checked was declared. 177static SourceLocation global_last_parameter_location; 178 179// List of all currently allocated blocks. 180static ListNode global_allocated_blocks; 181 182#ifndef _WIN32 183// Signals caught by exception_handler(). 184static const int exception_signals[] = { 185 SIGFPE, 186 SIGILL, 187 SIGSEGV, 188 SIGBUS, 189 SIGSYS, 190}; 191 192// Default signal functions that should be restored after a test is complete. 193typedef void (*SignalFunction)(int signal); 194static SignalFunction default_signal_functions[ 195 ARRAY_LENGTH(exception_signals)]; 196 197#else // _WIN32 198 199// The default exception filter. 200static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter; 201 202// Fatal exceptions. 203typedef struct ExceptionCodeInfo { 204 DWORD code; 205 const char* description; 206} ExceptionCodeInfo; 207 208#define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code} 209 210static const ExceptionCodeInfo exception_codes[] = { 211 EXCEPTION_CODE_INFO(EXCEPTION_ACCESS_VIOLATION), 212 EXCEPTION_CODE_INFO(EXCEPTION_ARRAY_BOUNDS_EXCEEDED), 213 EXCEPTION_CODE_INFO(EXCEPTION_DATATYPE_MISALIGNMENT), 214 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DENORMAL_OPERAND), 215 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DIVIDE_BY_ZERO), 216 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INEXACT_RESULT), 217 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INVALID_OPERATION), 218 EXCEPTION_CODE_INFO(EXCEPTION_FLT_OVERFLOW), 219 EXCEPTION_CODE_INFO(EXCEPTION_FLT_STACK_CHECK), 220 EXCEPTION_CODE_INFO(EXCEPTION_FLT_UNDERFLOW), 221 EXCEPTION_CODE_INFO(EXCEPTION_GUARD_PAGE), 222 EXCEPTION_CODE_INFO(EXCEPTION_ILLEGAL_INSTRUCTION), 223 EXCEPTION_CODE_INFO(EXCEPTION_INT_DIVIDE_BY_ZERO), 224 EXCEPTION_CODE_INFO(EXCEPTION_INT_OVERFLOW), 225 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_DISPOSITION), 226 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_HANDLE), 227 EXCEPTION_CODE_INFO(EXCEPTION_IN_PAGE_ERROR), 228 EXCEPTION_CODE_INFO(EXCEPTION_NONCONTINUABLE_EXCEPTION), 229 EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION), 230 EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW), 231}; 232#endif // !_WIN32 233 234 235// Exit the currently executing test. 236static void exit_test(const int quit_application) { 237 if (global_running_test) { 238 longjmp(global_run_test_env, 1); 239 } else if (quit_application) { 240 exit(-1); 241 } 242} 243 244 245// Initialize a SourceLocation structure. 246static void initialize_source_location(SourceLocation * const location) { 247 assert_true(location); 248 location->file = NULL; 249 location->line = 0; 250} 251 252 253// Determine whether a source location is currently set. 254static int source_location_is_set(const SourceLocation * const location) { 255 assert_true(location); 256 return location->file && location->line; 257} 258 259 260// Set a source location. 261static void set_source_location( 262 SourceLocation * const location, const char * const file, 263 const int line) { 264 assert_true(location); 265 location->file = file; 266 location->line = line; 267} 268 269 270// Create function results and expected parameter lists. 271void initialize_testing(const char *test_name) { 272 list_initialize(&global_function_result_map_head); 273 initialize_source_location(&global_last_mock_value_location); 274 list_initialize(&global_function_parameter_map_head); 275 initialize_source_location(&global_last_parameter_location); 276} 277 278 279void fail_if_leftover_values(const char *test_name) { 280 int error_occurred = 0; 281 remove_always_return_values(&global_function_result_map_head, 1); 282 if (check_for_leftover_values( 283 &global_function_result_map_head, 284 "%s() has remaining non-returned values.\n", 1)) { 285 error_occurred = 1; 286 } 287 288 remove_always_return_values(&global_function_parameter_map_head, 2); 289 if (check_for_leftover_values( 290 &global_function_parameter_map_head, 291 "%s parameter still has values that haven't been checked.\n", 2)) { 292 error_occurred = 1; 293 } 294 if (error_occurred) { 295 exit_test(1); 296 } 297} 298 299 300void teardown_testing(const char *test_name) { 301 list_free(&global_function_result_map_head, free_symbol_map_value, 302 (void*)0); 303 initialize_source_location(&global_last_mock_value_location); 304 list_free(&global_function_parameter_map_head, free_symbol_map_value, 305 (void*)1); 306 initialize_source_location(&global_last_parameter_location); 307} 308 309// Initialize a list node. 310static ListNode* list_initialize(ListNode * const node) { 311 node->value = NULL; 312 node->next = node; 313 node->prev = node; 314 node->refcount = 1; 315 return node; 316} 317 318 319/* Adds a value at the tail of a given list. 320 * The node referencing the value is allocated from the heap. */ 321static ListNode* list_add_value(ListNode * const head, const void *value, 322 const int refcount) { 323 ListNode * const new_node = (ListNode*)malloc(sizeof(ListNode)); 324 assert_true(head); 325 assert_true(value); 326 new_node->value = value; 327 new_node->refcount = refcount; 328 return list_add(head, new_node); 329} 330 331 332// Add new_node to the end of the list. 333static ListNode* list_add(ListNode * const head, ListNode *new_node) { 334 assert_true(head); 335 assert_true(new_node); 336 new_node->next = head; 337 new_node->prev = head->prev; 338 head->prev->next = new_node; 339 head->prev = new_node; 340 return new_node; 341} 342 343 344// Remove a node from a list. 345static ListNode* list_remove( 346 ListNode * const node, const CleanupListValue cleanup_value, 347 void * const cleanup_value_data) { 348 assert_true(node); 349 node->prev->next = node->next; 350 node->next->prev = node->prev; 351 if (cleanup_value) { 352 cleanup_value(node->value, cleanup_value_data); 353 } 354 return node; 355} 356 357 358/* Remove a list node from a list and free the node. */ 359static void list_remove_free( 360 ListNode * const node, const CleanupListValue cleanup_value, 361 void * const cleanup_value_data) { 362 assert_true(node); 363 free(list_remove(node, cleanup_value, cleanup_value_data)); 364} 365 366 367/* Frees memory kept by a linked list 368 * The cleanup_value function is called for every "value" field of nodes in the 369 * list, except for the head. In addition to each list value, 370 * cleanup_value_data is passed to each call to cleanup_value. The head 371 * of the list is not deallocated. 372 */ 373static ListNode* list_free( 374 ListNode * const head, const CleanupListValue cleanup_value, 375 void * const cleanup_value_data) { 376 assert_true(head); 377 while (!list_empty(head)) { 378 list_remove_free(head->next, cleanup_value, cleanup_value_data); 379 } 380 return head; 381} 382 383 384// Determine whether a list is empty. 385static int list_empty(const ListNode * const head) { 386 assert_true(head); 387 return head->next == head; 388} 389 390 391/* Find a value in the list using the equal_func to compare each node with the 392 * value. 393 */ 394static int list_find(ListNode * const head, const void *value, 395 const EqualityFunction equal_func, ListNode **output) { 396 ListNode *current; 397 assert_true(head); 398 for (current = head->next; current != head; current = current->next) { 399 if (equal_func(current->value, value)) { 400 *output = current; 401 return 1; 402 } 403 } 404 return 0; 405} 406 407// Returns the first node of a list 408static int list_first(ListNode * const head, ListNode **output) { 409 ListNode *target_node; 410 assert_true(head); 411 if (list_empty(head)) { 412 return 0; 413 } 414 target_node = head->next; 415 *output = target_node; 416 return 1; 417} 418 419 420// Deallocate a value referenced by a list. 421static void free_value(const void *value, void *cleanup_value_data) { 422 assert_true(value); 423 free((void*)value); 424} 425 426 427// Releases memory associated to a symbol_map_value. 428static void free_symbol_map_value(const void *value, 429 void *cleanup_value_data) { 430 SymbolMapValue * const map_value = (SymbolMapValue*)value; 431 const unsigned int children = (unsigned int)cleanup_value_data; 432 assert_true(value); 433 list_free(&map_value->symbol_values_list_head, 434 children ? free_symbol_map_value : free_value, 435 (void*)(children - 1)); 436 free(map_value); 437} 438 439 440/* Determine whether a symbol name referenced by a symbol_map_value 441 * matches the specified function name. */ 442static int symbol_names_match(const void *map_value, const void *symbol) { 443 return !strcmp(((SymbolMapValue*)map_value)->symbol_name, 444 (const char*)symbol); 445} 446 447 448/* Adds a value to the queue of values associated with the given 449 * hierarchy of symbols. It's assumed value is allocated from the heap. 450 */ 451static void add_symbol_value(ListNode * const symbol_map_head, 452 const char * const symbol_names[], 453 const size_t number_of_symbol_names, 454 const void* value, const int refcount) { 455 const char* symbol_name; 456 ListNode *target_node; 457 SymbolMapValue *target_map_value; 458 assert_true(symbol_map_head); 459 assert_true(symbol_names); 460 assert_true(number_of_symbol_names); 461 symbol_name = symbol_names[0]; 462 463 if (!list_find(symbol_map_head, symbol_name, symbol_names_match, 464 &target_node)) { 465 SymbolMapValue * const new_symbol_map_value = 466 malloc(sizeof(*new_symbol_map_value)); 467 new_symbol_map_value->symbol_name = symbol_name; 468 list_initialize(&new_symbol_map_value->symbol_values_list_head); 469 target_node = list_add_value(symbol_map_head, new_symbol_map_value, 470 1); 471 } 472 473 target_map_value = (SymbolMapValue*)target_node->value; 474 if (number_of_symbol_names == 1) { 475 list_add_value(&target_map_value->symbol_values_list_head, 476 value, refcount); 477 } else { 478 add_symbol_value(&target_map_value->symbol_values_list_head, 479 &symbol_names[1], number_of_symbol_names - 1, value, 480 refcount); 481 } 482} 483 484 485/* Gets the next value associated with the given hierarchy of symbols. 486 * The value is returned as an output parameter with the function returning the 487 * node's old refcount value if a value is found, 0 otherwise. 488 * This means that a return value of 1 indicates the node was just removed from 489 * the list. 490 */ 491static int get_symbol_value( 492 ListNode * const head, const char * const symbol_names[], 493 const size_t number_of_symbol_names, void **output) { 494 const char* symbol_name; 495 ListNode *target_node; 496 assert_true(head); 497 assert_true(symbol_names); 498 assert_true(number_of_symbol_names); 499 assert_true(output); 500 symbol_name = symbol_names[0]; 501 502 if (list_find(head, symbol_name, symbol_names_match, &target_node)) { 503 SymbolMapValue *map_value; 504 ListNode *child_list; 505 int return_value = 0; 506 assert_true(target_node); 507 assert_true(target_node->value); 508 509 map_value = (SymbolMapValue*)target_node->value; 510 child_list = &map_value->symbol_values_list_head; 511 512 if (number_of_symbol_names == 1) { 513 ListNode *value_node = NULL; 514 return_value = list_first(child_list, &value_node); 515 assert_true(return_value); 516 *output = (void*) value_node->value; 517 return_value = value_node->refcount; 518 if (--value_node->refcount == 0) { 519 list_remove_free(value_node, NULL, NULL); 520 } 521 } else { 522 return_value = get_symbol_value( 523 child_list, &symbol_names[1], number_of_symbol_names - 1, 524 output); 525 } 526 if (list_empty(child_list)) { 527 list_remove_free(target_node, free_symbol_map_value, (void*)0); 528 } 529 return return_value; 530 } else { 531 print_error("No entries for symbol %s.\n", symbol_name); 532 } 533 return 0; 534} 535 536 537/* Traverse down a tree of symbol values and remove the first symbol value 538 * in each branch that has a refcount < -1 (i.e should always be returned 539 * and has been returned at least once). 540 */ 541static void remove_always_return_values(ListNode * const map_head, 542 const size_t number_of_symbol_names) { 543 ListNode *current; 544 assert_true(map_head); 545 assert_true(number_of_symbol_names); 546 current = map_head->next; 547 while (current != map_head) { 548 SymbolMapValue * const value = (SymbolMapValue*)current->value; 549 ListNode * const next = current->next; 550 ListNode *child_list; 551 assert_true(value); 552 child_list = &value->symbol_values_list_head; 553 554 if (!list_empty(child_list)) { 555 if (number_of_symbol_names == 1) { 556 ListNode * const child_node = child_list->next; 557 // If this item has been returned more than once, free it. 558 if (child_node->refcount < -1) { 559 list_remove_free(child_node, free_value, NULL); 560 } 561 } else { 562 remove_always_return_values(child_list, 563 number_of_symbol_names - 1); 564 } 565 } 566 567 if (list_empty(child_list)) { 568 list_remove_free(current, free_value, NULL); 569 } 570 current = next; 571 } 572} 573 574/* Checks if there are any leftover values set up by the test that were never 575 * retrieved through execution, and fail the test if that is the case. 576 */ 577static int check_for_leftover_values( 578 const ListNode * const map_head, const char * const error_message, 579 const size_t number_of_symbol_names) { 580 const ListNode *current; 581 int symbols_with_leftover_values = 0; 582 assert_true(map_head); 583 assert_true(number_of_symbol_names); 584 585 for (current = map_head->next; current != map_head; 586 current = current->next) { 587 const SymbolMapValue * const value = 588 (SymbolMapValue*)current->value; 589 const ListNode *child_list; 590 assert_true(value); 591 child_list = &value->symbol_values_list_head; 592 593 if (!list_empty(child_list)) { 594 if (number_of_symbol_names == 1) { 595 const ListNode *child_node; 596 print_error(error_message, value->symbol_name); 597 print_error(" Remaining item(s) declared at...\n"); 598 599 for (child_node = child_list->next; child_node != child_list; 600 child_node = child_node->next) { 601 const SourceLocation * const location = child_node->value; 602 print_error(" " SOURCE_LOCATION_FORMAT "\n", 603 location->file, location->line); 604 } 605 } else { 606 print_error("%s.", value->symbol_name); 607 check_for_leftover_values(child_list, error_message, 608 number_of_symbol_names - 1); 609 } 610 symbols_with_leftover_values ++; 611 } 612 } 613 return symbols_with_leftover_values; 614} 615 616 617// Get the next return value for the specified mock function. 618void* _mock(const char * const function, const char* const file, 619 const int line) { 620 void *result; 621 const int rc = get_symbol_value(&global_function_result_map_head, 622 &function, 1, &result); 623 if (rc) { 624 SymbolValue * const symbol = result; 625 void * const value = (void*)symbol->value; 626 global_last_mock_value_location = symbol->location; 627 if (rc == 1) { 628 free(symbol); 629 } 630 return value; 631 } else { 632 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value " 633 "to mock function %s\n", file, line, function); 634 if (source_location_is_set(&global_last_mock_value_location)) { 635 print_error("Previously returned mock value was declared at " 636 SOURCE_LOCATION_FORMAT "\n", 637 global_last_mock_value_location.file, 638 global_last_mock_value_location.line); 639 } else { 640 print_error("There were no previously returned mock values for " 641 "this test.\n"); 642 } 643 exit_test(1); 644 } 645 return NULL; 646} 647 648 649// Add a return value for the specified mock function name. 650void _will_return(const char * const function_name, const char * const file, 651 const int line, const void* const value, const int count) { 652 SymbolValue * const return_value = malloc(sizeof(*return_value)); 653 assert_true(count > 0); 654 return_value->value = value; 655 set_source_location(&return_value->location, file, line); 656 add_symbol_value(&global_function_result_map_head, &function_name, 1, 657 return_value, count); 658} 659 660 661/* Add a custom parameter checking function. If the event parameter is NULL 662 * the event structure is allocated internally by this function. If event 663 * parameter is provided it must be allocated on the heap and doesn't need to 664 * be deallocated by the caller. 665 */ 666void _expect_check( 667 const char* const function, const char* const parameter, 668 const char* const file, const int line, 669 const CheckParameterValue check_function, void * const check_data, 670 CheckParameterEvent * const event, const int count) { 671 CheckParameterEvent * const check = 672 event ? event : malloc(sizeof(*check)); 673 const char* symbols[] = {function, parameter}; 674 check->parameter_name = parameter; 675 check->check_value = check_function; 676 check->check_value_data = check_data; 677 set_source_location(&check->location, file, line); 678 add_symbol_value(&global_function_parameter_map_head, symbols, 2, check, 679 count); 680} 681 682 683/* Returns 1 if the specified values are equal. If the values are not equal 684 * an error is displayed and 0 is returned. */ 685static int values_equal_display_error(const void* const left, 686 const void* const right) { 687 const int equal = left == right; 688 if (!equal) { 689 print_error("0x%x != 0x%x\n", left, right); 690 } 691 return equal; 692} 693 694/* Returns 1 if the specified values are not equal. If the values are equal 695 * an error is displayed and 0 is returned. */ 696static int values_not_equal_display_error(const void* const left, 697 const void* const right) { 698 const int not_equal = left != right; 699 if (!not_equal) { 700 print_error("0x%x == 0x%x\n", left, right); 701 } 702 return not_equal; 703} 704 705 706/* Determine whether value is contained within check_integer_set. 707 * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is 708 * returned and an error is displayed. If invert is 1 and the value is not 709 * in the set 1 is returned, otherwise 0 is returned and an error is 710 * displayed. */ 711static int value_in_set_display_error( 712 const void *value, const CheckIntegerSet * const check_integer_set, 713 const int invert) { 714 int succeeded = invert; 715 assert_true(check_integer_set); 716 { 717 const void ** const set = check_integer_set->set; 718 const size_t size_of_set = check_integer_set->size_of_set; 719 size_t i; 720 for (i = 0; i < size_of_set; i++) { 721 if (set[i] == value) { 722 if (invert) { 723 succeeded = 0; 724 } 725 break; 726 } 727 } 728 if (succeeded) { 729 return 1; 730 } 731 print_error("%d is %sin the set (", value, invert ? "" : "not "); 732 for (i = 0; i < size_of_set; i++) { 733 print_error("%d, ", set[i]); 734 } 735 print_error(")\n"); 736 } 737 return 0; 738} 739 740 741/* Determine whether a value is within the specified range. If the value is 742 * within the specified range 1 is returned. If the value isn't within the 743 * specified range an error is displayed and 0 is returned. */ 744static int integer_in_range_display_error( 745 const int value, const int range_min, const int range_max) { 746 if (value >= range_min && value <= range_max) { 747 return 1; 748 } 749 print_error("%d is not within the range %d-%d\n", value, range_min, 750 range_max); 751 return 0; 752} 753 754 755/* Determine whether a value is within the specified range. If the value 756 * is not within the range 1 is returned. If the value is within the 757 * specified range an error is displayed and zero is returned. */ 758static int integer_not_in_range_display_error( 759 const int value, const int range_min, const int range_max) { 760 if (value < range_min || value > range_max) { 761 return 1; 762 } 763 print_error("%d is within the range %d-%d\n", value, range_min, 764 range_max); 765 return 0; 766} 767 768 769/* Determine whether the specified strings are equal. If the strings are equal 770 * 1 is returned. If they're not equal an error is displayed and 0 is 771 * returned. */ 772static int string_equal_display_error( 773 const char * const left, const char * const right) { 774 if (strcmp(left, right) == 0) { 775 return 1; 776 } 777 print_error("\"%s\" != \"%s\"\n", left, right); 778 return 0; 779} 780 781 782/* Determine whether the specified strings are equal. If the strings are not 783 * equal 1 is returned. If they're not equal an error is displayed and 0 is 784 * returned */ 785static int string_not_equal_display_error( 786 const char * const left, const char * const right) { 787 if (strcmp(left, right) != 0) { 788 return 1; 789 } 790 print_error("\"%s\" == \"%s\"\n", left, right); 791 return 0; 792} 793 794 795/* Determine whether the specified areas of memory are equal. If they're equal 796 * 1 is returned otherwise an error is displayed and 0 is returned. */ 797static int memory_equal_display_error(const char* a, const char* b, 798 const size_t size) { 799 int differences = 0; 800 size_t i; 801 for (i = 0; i < size; i++) { 802 const char l = a[i]; 803 const char r = b[i]; 804 if (l != r) { 805 print_error("difference at offset %d 0x%02x 0x%02x\n", i, l, r); 806 differences ++; 807 } 808 } 809 if (differences) { 810 print_error("%d bytes of 0x%08x and 0x%08x differ\n", differences, 811 a, b); 812 return 0; 813 } 814 return 1; 815} 816 817 818/* Determine whether the specified areas of memory are not equal. If they're 819 * not equal 1 is returned otherwise an error is displayed and 0 is 820 * returned. */ 821static int memory_not_equal_display_error(const char* a, const char* b, 822 const size_t size) { 823 int same = 0; 824 size_t i; 825 for (i = 0; i < size; i++) { 826 const char l = a[i]; 827 const char r = b[i]; 828 if (l == r) { 829 print_error("equal at offset %d 0x%02x 0x%02x\n", i, l, r); 830 same ++; 831 } 832 } 833 if (same) { 834 print_error("%d bytes of 0x%08x and 0x%08x the same\n", same, 835 a, b); 836 return 0; 837 } 838 return 1; 839} 840 841 842// CheckParameterValue callback to check whether a value is within a set. 843static int check_in_set(const void *value, void *check_value_data) { 844 return value_in_set_display_error(value, 845 (CheckIntegerSet*)check_value_data, 0); 846} 847 848 849// CheckParameterValue callback to check whether a value isn't within a set. 850static int check_not_in_set(const void *value, void *check_value_data) { 851 return value_in_set_display_error(value, 852 (CheckIntegerSet*)check_value_data, 1); 853} 854 855 856/* Create the callback data for check_in_set() or check_not_in_set() and 857 * register a check event. */ 858static void expect_set( 859 const char* const function, const char* const parameter, 860 const char* const file, const int line, const void *values[], 861 const size_t number_of_values, 862 const CheckParameterValue check_function, const int count) { 863 CheckIntegerSet * const check_integer_set = 864 malloc(sizeof(*check_integer_set) + 865 (sizeof(values[0]) * number_of_values)); 866 void ** const set = (void**)(check_integer_set + 1); 867 assert_true(values); 868 assert_true(number_of_values); 869 memcpy(set, values, number_of_values * sizeof(values[0])); 870 check_integer_set->set = (const void**)set; 871 _expect_check(function, parameter, file, line, check_function, 872 check_integer_set, &check_integer_set->event, count); 873} 874 875 876// Add an event to check whether a value is in a set. 877void _expect_in_set( 878 const char* const function, const char* const parameter, 879 const char* const file, const int line, const void *values[], 880 const size_t number_of_values, const int count) { 881 expect_set(function, parameter, file, line, values, number_of_values, 882 check_in_set, count); 883} 884 885 886// Add an event to check whether a value isn't in a set. 887void _expect_not_in_set( 888 const char* const function, const char* const parameter, 889 const char* const file, const int line, const void *values[], 890 const size_t number_of_values, const int count) { 891 expect_set(function, parameter, file, line, values, number_of_values, 892 check_not_in_set, count); 893} 894 895 896// CheckParameterValue callback to check whether a value is within a range. 897static int check_in_range(const void *value, void *check_value_data) { 898 CheckIntegerRange * const check_integer_range = check_value_data; 899 assert_true(check_value_data); 900 return integer_in_range_display_error( 901 (int)value, check_integer_range->minimum, 902 check_integer_range->maximum); 903} 904 905 906// CheckParameterValue callback to check whether a value is not within a range. 907static int check_not_in_range(const void *value, void *check_value_data) { 908 CheckIntegerRange * const check_integer_range = check_value_data; 909 assert_true(check_value_data); 910 return integer_not_in_range_display_error( 911 (int)value, check_integer_range->minimum, 912 check_integer_range->maximum); 913} 914 915 916/* Create the callback data for check_in_range() or check_not_in_range() and 917 * register a check event. */ 918static void expect_range( 919 const char* const function, const char* const parameter, 920 const char* const file, const int line, 921 const int minimum, const int maximum, 922 const CheckParameterValue check_function, const int count) { 923 CheckIntegerRange * const check_integer_range = 924 malloc(sizeof(*check_integer_range)); 925 check_integer_range->minimum = minimum; 926 check_integer_range->maximum = maximum; 927 _expect_check(function, parameter, file, line, check_function, 928 check_integer_range, &check_integer_range->event, count); 929} 930 931 932// Add an event to determine whether a parameter is within a range. 933void _expect_in_range( 934 const char* const function, const char* const parameter, 935 const char* const file, const int line, 936 const int minimum, const int maximum, const int count) { 937 expect_range(function, parameter, file, line, minimum, maximum, 938 check_in_range, count); 939} 940 941 942// Add an event to determine whether a parameter is not within a range. 943void _expect_not_in_range( 944 const char* const function, const char* const parameter, 945 const char* const file, const int line, 946 const int minimum, const int maximum, const int count) { 947 expect_range(function, parameter, file, line, minimum, maximum, 948 check_not_in_range, count); 949} 950 951 952/* CheckParameterValue callback to check whether a value is equal to an 953 * expected value. */ 954static int check_value(const void *value, void *check_value_data) { 955 return values_equal_display_error(value, check_value_data); 956} 957 958 959// Add an event to check a parameter equals an expected value. 960void _expect_value( 961 const char* const function, const char* const parameter, 962 const char* const file, const int line, const void* const value, 963 const int count) { 964 _expect_check(function, parameter, file, line, check_value, 965 (void*)value, NULL, count); 966} 967 968 969/* CheckParameterValue callback to check whether a value is not equal to an 970 * expected value. */ 971static int check_not_value(const void *value, void *check_value_data) { 972 return values_not_equal_display_error(value, check_value_data); 973} 974 975 976// Add an event to check a parameter is not equal to an expected value. 977void _expect_not_value( 978 const char* const function, const char* const parameter, 979 const char* const file, const int line, const void* const value, 980 const int count) { 981 _expect_check(function, parameter, file, line, check_not_value, 982 (void*)value, NULL, count); 983} 984 985 986// CheckParameterValue callback to check whether a parameter equals a string. 987static int check_string(const void * value, void *check_value_data) { 988 return string_equal_display_error(value, check_value_data); 989} 990 991 992// Add an event to check whether a parameter is equal to a string. 993void _expect_string( 994 const char* const function, const char* const parameter, 995 const char* const file, const int line, const char* string, 996 const int count) { 997 _expect_check(function, parameter, file, line, check_string, (void*)string, 998 NULL, count); 999} 1000 1001 1002/* CheckParameterValue callback to check whether a parameter is not equals to 1003 * a string. */ 1004static int check_not_string(const void * value, void *check_value_data) { 1005 return string_not_equal_display_error(value, check_value_data); 1006} 1007 1008 1009// Add an event to check whether a parameter is not equal to a string. 1010void _expect_not_string( 1011 const char* const function, const char* const parameter, 1012 const char* const file, const int line, const char* string, 1013 const int count) { 1014 _expect_check(function, parameter, file, line, check_not_string, 1015 (void*)string, NULL, count); 1016} 1017 1018/* CheckParameterValue callback to check whether a parameter equals an area of 1019 * memory. */ 1020static int check_memory(const void* value, void *check_value_data) { 1021 CheckMemoryData * const check = (CheckMemoryData*)check_value_data; 1022 assert_true(check); 1023 return memory_equal_display_error(value, check->memory, check->size); 1024} 1025 1026 1027/* Create the callback data for check_memory() or check_not_memory() and 1028 * register a check event. */ 1029static void expect_memory_setup( 1030 const char* const function, const char* const parameter, 1031 const char* const file, const int line, 1032 const void * const memory, const size_t size, 1033 const CheckParameterValue check_function, const int count) { 1034 CheckMemoryData * const check_data = malloc(sizeof(*check_data) + size); 1035 void * const mem = (void*)(check_data + 1); 1036 assert_true(memory); 1037 assert_true(size); 1038 memcpy(mem, memory, size); 1039 check_data->memory = mem; 1040 check_data->size = size; 1041 _expect_check(function, parameter, file, line, check_function, 1042 check_data, &check_data->event, count); 1043} 1044 1045 1046// Add an event to check whether a parameter matches an area of memory. 1047void _expect_memory( 1048 const char* const function, const char* const parameter, 1049 const char* const file, const int line, const void* const memory, 1050 const size_t size, const int count) { 1051 expect_memory_setup(function, parameter, file, line, memory, size, 1052 check_memory, count); 1053} 1054 1055 1056/* CheckParameterValue callback to check whether a parameter is not equal to 1057 * an area of memory. */ 1058static int check_not_memory(const void* value, void *check_value_data) { 1059 CheckMemoryData * const check = (CheckMemoryData*)check_value_data; 1060 assert_true(check); 1061 return memory_not_equal_display_error(value, check->memory, check->size); 1062} 1063 1064 1065// Add an event to check whether a parameter doesn't match an area of memory. 1066void _expect_not_memory( 1067 const char* const function, const char* const parameter, 1068 const char* const file, const int line, const void* const memory, 1069 const size_t size, const int count) { 1070 expect_memory_setup(function, parameter, file, line, memory, size, 1071 check_not_memory, count); 1072} 1073 1074 1075// CheckParameterValue callback that always returns 1. 1076static int check_any(const void *value, void *check_value_data) { 1077 return 1; 1078} 1079 1080 1081// Add an event to allow any value for a parameter. 1082void _expect_any( 1083 const char* const function, const char* const parameter, 1084 const char* const file, const int line, const int count) { 1085 _expect_check(function, parameter, file, line, check_any, NULL, NULL, 1086 count); 1087} 1088 1089 1090void _check_expected( 1091 const char * const function_name, const char * const parameter_name, 1092 const char* file, const int line, const void* value) { 1093 void *result; 1094 const char* symbols[] = {function_name, parameter_name}; 1095 const int rc = get_symbol_value(&global_function_parameter_map_head, 1096 symbols, 2, &result); 1097 if (rc) { 1098 CheckParameterEvent * const check = (CheckParameterEvent*)result; 1099 int check_succeeded; 1100 global_last_parameter_location = check->location; 1101 check_succeeded = check->check_value(value, check->check_value_data); 1102 if (rc == 1) { 1103 free(check); 1104 } 1105 if (!check_succeeded) { 1106 print_error("ERROR: Check of parameter %s, function %s failed\n" 1107 "Expected parameter declared at " 1108 SOURCE_LOCATION_FORMAT "\n", 1109 parameter_name, function_name, 1110 global_last_parameter_location.file, 1111 global_last_parameter_location.line); 1112 _fail(file, line); 1113 } 1114 } else { 1115 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value " 1116 "to check parameter %s of function %s\n", file, line, 1117 parameter_name, function_name); 1118 if (source_location_is_set(&global_last_parameter_location)) { 1119 print_error("Previously declared parameter value was declared at " 1120 SOURCE_LOCATION_FORMAT "\n", 1121 global_last_parameter_location.file, 1122 global_last_parameter_location.line); 1123 } else { 1124 print_error("There were no previously declared parameter values " 1125 "for this test.\n"); 1126 } 1127 exit_test(1); 1128 } 1129} 1130 1131 1132// Replacement for assert. 1133void mock_assert(const int result, const char* const expression, 1134 const char* const file, const int line) { 1135 if (!result) { 1136 if (global_expecting_assert) { 1137 longjmp(global_expect_assert_env, (int)expression); 1138 } else { 1139 print_error("ASSERT: %s\n", expression); 1140 _fail(file, line); 1141 } 1142 } 1143} 1144 1145 1146void _assert_true(const int result, const char * const expression, 1147 const char * const file, const int line) { 1148 if (!result) { 1149 print_error("%s\n", expression); 1150 _fail(file, line); 1151 } 1152} 1153 1154void _assert_int_equal(const int a, const int b, const char * const file, 1155 const int line) { 1156 if (!values_equal_display_error((void*)a, (void*)b)) { 1157 _fail(file, line); 1158 } 1159} 1160 1161 1162void _assert_int_not_equal(const int a, const int b, const char * const file, 1163 const int line) { 1164 if (!values_not_equal_display_error((void*)a, (void*)b)) { 1165 _fail(file, line); 1166 } 1167} 1168 1169 1170void _assert_string_equal(const char * const a, const char * const b, 1171 const char * const file, const int line) { 1172 if (!string_equal_display_error(a, b)) { 1173 _fail(file, line); 1174 } 1175} 1176 1177 1178void _assert_string_not_equal(const char * const a, const char * const b, 1179 const char *file, const int line) { 1180 if (!string_not_equal_display_error(a, b)) { 1181 _fail(file, line); 1182 } 1183} 1184 1185 1186void _assert_memory_equal(const void * const a, const void * const b, 1187 const size_t size, const char* const file, 1188 const int line) { 1189 if (!memory_equal_display_error((const char*)a, (const char*)b, size)) { 1190 _fail(file, line); 1191 } 1192} 1193 1194 1195void _assert_memory_not_equal(const void * const a, const void * const b, 1196 const size_t size, const char* const file, 1197 const int line) { 1198 if (!memory_not_equal_display_error((const char*)a, (const char*)b, 1199 size)) { 1200 _fail(file, line); 1201 } 1202} 1203 1204 1205void _assert_in_range(const int value, const int minimum, const int maximum, 1206 const char* const file, const int line) { 1207 if (!integer_in_range_display_error(value, minimum, maximum)) { 1208 _fail(file, line); 1209 } 1210} 1211 1212void _assert_not_in_range(const int value, const int minimum, 1213 const int maximum, const char* const file, 1214 const int line) { 1215 if (!integer_not_in_range_display_error(value, minimum, maximum)) { 1216 _fail(file, line); 1217 } 1218} 1219 1220void _assert_in_set(const void* const value, const void *values[], 1221 const size_t number_of_values, const char* const file, 1222 const int line) { 1223 CheckIntegerSet check_integer_set; 1224 check_integer_set.set = values; 1225 check_integer_set.size_of_set = number_of_values; 1226 if (!value_in_set_display_error(value, &check_integer_set, 0)) { 1227 _fail(file, line); 1228 } 1229} 1230 1231void _assert_not_in_set(const void* const value, const void *values[], 1232 const size_t number_of_values, const char* const file, 1233 const int line) { 1234 CheckIntegerSet check_integer_set; 1235 check_integer_set.set = values; 1236 check_integer_set.size_of_set = number_of_values; 1237 if (!value_in_set_display_error(value, &check_integer_set, 1)) { 1238 _fail(file, line); 1239 } 1240} 1241 1242 1243// Get the list of allocated blocks. 1244static ListNode* get_allocated_blocks_list() { 1245 // If it initialized, initialize the list of allocated blocks. 1246 if (!global_allocated_blocks.value) { 1247 list_initialize(&global_allocated_blocks); 1248 global_allocated_blocks.value = (void*)1; 1249 } 1250 return &global_allocated_blocks; 1251} 1252 1253// Use the real malloc in this function. 1254#undef malloc 1255void* _test_malloc(const size_t size, const char* file, const int line) { 1256 char* ptr; 1257 MallocBlockInfo *block_info; 1258 ListNode * const block_list = get_allocated_blocks_list(); 1259 const size_t allocate_size = size + (MALLOC_GUARD_SIZE * 2) + 1260 sizeof(*block_info) + MALLOC_ALIGNMENT; 1261 char* const block = (char*)malloc(allocate_size); 1262 assert_true(block); 1263 1264 // Calculate the returned address. 1265 ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE + sizeof(*block_info) + 1266 MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1)); 1267 1268 // Initialize the guard blocks. 1269 memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE); 1270 memset(ptr + size, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE); 1271 memset(ptr, MALLOC_ALLOC_PATTERN, size); 1272 1273 block_info = (MallocBlockInfo*)(ptr - (MALLOC_GUARD_SIZE + 1274 sizeof(*block_info))); 1275 set_source_location(&block_info->location, file, line); 1276 block_info->allocated_size = allocate_size; 1277 block_info->size = size; 1278 block_info->block = block; 1279 block_info->node.value = block_info; 1280 list_add(block_list, &block_info->node); 1281 return ptr; 1282} 1283#define malloc test_malloc 1284 1285 1286void* _test_calloc(const size_t number_of_elements, const size_t size, 1287 const char* file, const int line) { 1288 void* const ptr = _test_malloc(number_of_elements * size, file, line); 1289 if (ptr) { 1290 memset(ptr, 0, number_of_elements * size); 1291 } 1292 return ptr; 1293} 1294 1295 1296// Use the real free in this function. 1297#undef free 1298void _test_free(void* const ptr, const char* file, const int line) { 1299 unsigned int i; 1300 char *block = (char*)ptr; 1301 MallocBlockInfo *block_info; 1302 _assert_true((int)ptr, "ptr", file, line); 1303 block_info = (MallocBlockInfo*)(block - (MALLOC_GUARD_SIZE + 1304 sizeof(*block_info))); 1305 // Check the guard blocks. 1306 { 1307 char *guards[2] = {block - MALLOC_GUARD_SIZE, 1308 block + block_info->size}; 1309 for (i = 0; i < ARRAY_LENGTH(guards); i++) { 1310 unsigned int j; 1311 char * const guard = guards[i]; 1312 for (j = 0; j < MALLOC_GUARD_SIZE; j++) { 1313 const char diff = guard[j] - MALLOC_GUARD_PATTERN; 1314 if (diff) { 1315 print_error( 1316 "Guard block of 0x%08x size=%d allocated by " 1317 SOURCE_LOCATION_FORMAT " at 0x%08x is corrupt\n", 1318 (size_t)ptr, block_info->size, 1319 block_info->location.file, block_info->location.line, 1320 (size_t)&guard[j]); 1321 _fail(file, line); 1322 } 1323 } 1324 } 1325 } 1326 list_remove(&block_info->node, NULL, NULL); 1327 1328 block = block_info->block; 1329 memset(block, MALLOC_FREE_PATTERN, block_info->allocated_size); 1330 free(block); 1331} 1332#define free test_free 1333 1334 1335// Crudely checkpoint the current heap state. 1336static const ListNode* check_point_allocated_blocks() { 1337 return get_allocated_blocks_list()->prev; 1338} 1339 1340 1341/* Display the blocks allocated after the specified check point. This 1342 * function returns the number of blocks displayed. */ 1343static int display_allocated_blocks(const ListNode * const check_point) { 1344 const ListNode * const head = get_allocated_blocks_list(); 1345 const ListNode *node; 1346 int allocated_blocks = 0; 1347 assert_true(check_point); 1348 assert_true(check_point->next); 1349 1350 for (node = check_point->next; node != head; node = node->next) { 1351 const MallocBlockInfo * const block_info = node->value; 1352 assert_true(block_info); 1353 1354 if (!allocated_blocks) { 1355 print_error("Blocks allocated...\n"); 1356 } 1357 print_error(" 0x%08x : " SOURCE_LOCATION_FORMAT "\n", 1358 block_info->block, block_info->location.file, 1359 block_info->location.line); 1360 allocated_blocks ++; 1361 } 1362 return allocated_blocks; 1363} 1364 1365 1366// Free all blocks allocated after the specified check point. 1367static void free_allocated_blocks(const ListNode * const check_point) { 1368 const ListNode * const head = get_allocated_blocks_list(); 1369 const ListNode *node; 1370 assert_true(check_point); 1371 1372 node = check_point->next; 1373 assert_true(node); 1374 1375 while (node != head) { 1376 MallocBlockInfo * const block_info = (MallocBlockInfo*)node->value; 1377 node = node->next; 1378 free((char*)block_info + sizeof(*block_info) + MALLOC_GUARD_SIZE); 1379 } 1380} 1381 1382 1383// Fail if any any blocks are allocated after the specified check point. 1384static void fail_if_blocks_allocated(const ListNode * const check_point, 1385 const char * const test_name) { 1386 const int allocated_blocks = display_allocated_blocks(check_point); 1387 if (allocated_blocks) { 1388 free_allocated_blocks(check_point); 1389 print_error("ERROR: %s leaked %d block(s)\n", test_name, 1390 allocated_blocks); 1391 exit_test(1); 1392 } 1393} 1394 1395 1396void _fail(const char * const file, const int line) { 1397 print_error("ERROR: " SOURCE_LOCATION_FORMAT " Failure!\n", file, line); 1398 exit_test(1); 1399} 1400 1401 1402#ifndef _WIN32 1403static void exception_handler(int sig) { 1404 print_error("%s\n", strsignal(sig)); 1405 exit_test(1); 1406} 1407 1408#else // _WIN32 1409 1410static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) { 1411 EXCEPTION_RECORD * const exception_record = 1412 exception_pointers->ExceptionRecord; 1413 const DWORD code = exception_record->ExceptionCode; 1414 unsigned int i; 1415 for (i = 0; i < ARRAY_LENGTH(exception_codes); i++) { 1416 const ExceptionCodeInfo * const code_info = &exception_codes[i]; 1417 if (code == code_info->code) { 1418 static int shown_debug_message = 0; 1419 fflush(stdout); 1420 print_error("%s occurred at 0x%08x.\n", code_info->description, 1421 exception_record->ExceptionAddress); 1422 if (!shown_debug_message) { 1423 print_error( 1424 "\n" 1425 "To debug in Visual Studio...\n" 1426 "1. Select menu item File->Open Project\n" 1427 "2. Change 'Files of type' to 'Executable Files'\n" 1428 "3. Open this executable.\n" 1429 "4. Select menu item Debug->Start\n" 1430 "\n" 1431 "Alternatively, set the environment variable \n" 1432 "UNIT_TESTING_DEBUG to 1 and rebuild this executable, \n" 1433 "then click 'Debug' in the popup dialog box.\n" 1434 "\n"); 1435 shown_debug_message = 1; 1436 } 1437 exit_test(0); 1438 return EXCEPTION_EXECUTE_HANDLER; 1439 } 1440 } 1441 return EXCEPTION_CONTINUE_SEARCH; 1442} 1443#endif // !_WIN32 1444 1445 1446// Standard output and error print methods. 1447void vprint_message(const char* const format, va_list args) { 1448 char buffer[1024]; 1449 vsnprintf(buffer, sizeof(buffer), format, args); 1450 printf(buffer); 1451#ifdef _WIN32 1452 OutputDebugString(buffer); 1453#endif // _WIN32 1454} 1455 1456 1457void vprint_error(const char* const format, va_list args) { 1458 char buffer[1024]; 1459 vsnprintf(buffer, sizeof(buffer), format, args); 1460 fprintf(stderr, buffer); 1461#ifdef _WIN32 1462 OutputDebugString(buffer); 1463#endif // _WIN32 1464} 1465 1466 1467void print_message(const char* const format, ...) { 1468 va_list args; 1469 va_start(args, format); 1470 vprint_message(format, args); 1471 va_end(args); 1472} 1473 1474 1475void print_error(const char* const format, ...) { 1476 va_list args; 1477 va_start(args, format); 1478 vprint_error(format, args); 1479 va_end(args); 1480} 1481 1482 1483int _run_test( 1484 const char * const function_name, const UnitTestFunction Function, 1485 void ** const state, const UnitTestFunctionType function_type, 1486 const void* const heap_check_point) { 1487 const ListNode * const check_point = heap_check_point ? 1488 heap_check_point : check_point_allocated_blocks(); 1489 void *current_state = NULL; 1490 int rc = 1; 1491 int handle_exceptions = 1; 1492#ifdef _WIN32 1493 handle_exceptions = !IsDebuggerPresent(); 1494#endif // _WIN32 1495#if UNIT_TESTING_DEBUG 1496 handle_exceptions = 0; 1497#endif // UNIT_TESTING_DEBUG 1498 1499 if (handle_exceptions) { 1500#ifndef _WIN32 1501 unsigned int i; 1502 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) { 1503 default_signal_functions[i] = signal( 1504 exception_signals[i], exception_handler); 1505 } 1506#else // _WIN32 1507 previous_exception_filter = SetUnhandledExceptionFilter( 1508 exception_filter); 1509#endif // !_WIN32 1510 } 1511 1512 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) { 1513 print_message("%s: Starting test\n", function_name); 1514 } 1515 initialize_testing(function_name); 1516 global_running_test = 1; 1517 if (setjmp(global_run_test_env) == 0) { 1518 Function(state ? state : ¤t_state); 1519 fail_if_leftover_values(function_name); 1520 1521 /* If this is a setup function then ignore any allocated blocks 1522 * only ensure they're deallocated on tear down. */ 1523 if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) { 1524 fail_if_blocks_allocated(check_point, function_name); 1525 } 1526 1527 global_running_test = 0; 1528 1529 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) { 1530 print_message("%s: Test completed successfully.\n", function_name); 1531 } 1532 rc = 0; 1533 } else { 1534 global_running_test = 0; 1535 print_message("%s: Test failed.\n", function_name); 1536 } 1537 teardown_testing(function_name); 1538 1539 if (handle_exceptions) { 1540#ifndef _WIN32 1541 unsigned int i; 1542 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) { 1543 signal(exception_signals[i], default_signal_functions[i]); 1544 } 1545#else // _WIN32 1546 if (previous_exception_filter) { 1547 SetUnhandledExceptionFilter(previous_exception_filter); 1548 previous_exception_filter = NULL; 1549 } 1550#endif // !_WIN32 1551 } 1552 1553 return rc; 1554} 1555 1556 1557int _run_tests(const UnitTest * const tests, const size_t number_of_tests) { 1558 // Whether to execute the next test. 1559 int run_next_test = 1; 1560 // Whether the previous test failed. 1561 int previous_test_failed = 0; 1562 // Check point of the heap state. 1563 const ListNode * const check_point = check_point_allocated_blocks(); 1564 // Current test being executed. 1565 size_t current_test = 0; 1566 // Number of tests executed. 1567 size_t tests_executed = 0; 1568 // Number of failed tests. 1569 size_t total_failed = 0; 1570 // Number of setup functions. 1571 size_t setups = 0; 1572 // Number of teardown functions. 1573 size_t teardowns = 0; 1574 /* A stack of test states. A state is pushed on the stack 1575 * when a test setup occurs and popped on tear down. */ 1576 TestState* test_states = malloc(number_of_tests * sizeof(*test_states)); 1577 size_t number_of_test_states = 0; 1578 // Names of the tests that failed. 1579 const char** failed_names = malloc(number_of_tests * 1580 sizeof(*failed_names)); 1581 void **current_state = NULL; 1582 1583 while (current_test < number_of_tests) { 1584 const ListNode *test_check_point = NULL; 1585 TestState *current_TestState; 1586 const UnitTest * const test = &tests[current_test++]; 1587 if (!test->function) { 1588 continue; 1589 } 1590 1591 switch (test->function_type) { 1592 case UNIT_TEST_FUNCTION_TYPE_TEST: 1593 run_next_test = 1; 1594 break; 1595 case UNIT_TEST_FUNCTION_TYPE_SETUP: { 1596 // Checkpoint the heap before the setup. 1597 current_TestState = &test_states[number_of_test_states++]; 1598 current_TestState->check_point = check_point_allocated_blocks(); 1599 test_check_point = current_TestState->check_point; 1600 current_state = ¤t_TestState->state; 1601 *current_state = NULL; 1602 run_next_test = 1; 1603 setups ++; 1604 break; 1605 } 1606 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN: 1607 // Check the heap based on the last setup checkpoint. 1608 assert_true(number_of_test_states); 1609 current_TestState = &test_states[--number_of_test_states]; 1610 test_check_point = current_TestState->check_point; 1611 current_state = ¤t_TestState->state; 1612 teardowns ++; 1613 break; 1614 default: 1615 print_error("Invalid unit test function type %d\n", 1616 test->function_type); 1617 exit_test(1); 1618 break; 1619 } 1620 1621 if (run_next_test) { 1622 int failed = _run_test(test->name, test->function, current_state, 1623 test->function_type, test_check_point); 1624 if (failed) { 1625 failed_names[total_failed] = test->name; 1626 } 1627 1628 switch (test->function_type) { 1629 case UNIT_TEST_FUNCTION_TYPE_TEST: 1630 previous_test_failed = failed; 1631 total_failed += failed; 1632 tests_executed ++; 1633 break; 1634 1635 case UNIT_TEST_FUNCTION_TYPE_SETUP: 1636 if (failed) { 1637 total_failed ++; 1638 tests_executed ++; 1639 // Skip forward until the next test or setup function. 1640 run_next_test = 0; 1641 } 1642 previous_test_failed = 0; 1643 break; 1644 1645 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN: 1646 // If this test failed. 1647 if (failed && !previous_test_failed) { 1648 total_failed ++; 1649 } 1650 break; 1651 default: 1652 assert_false("BUG: shouldn't be here!"); 1653 break; 1654 } 1655 } 1656 } 1657 1658 if (total_failed) { 1659 size_t i; 1660 print_error("%d out of %d tests failed!\n", total_failed, 1661 tests_executed); 1662 for (i = 0; i < total_failed; i++) { 1663 print_error(" %s\n", failed_names[i]); 1664 } 1665 } else { 1666 print_message("All %d tests passed\n", tests_executed); 1667 } 1668 1669 if (number_of_test_states) { 1670 print_error("Mismatched number of setup %d and teardown %d " 1671 "functions\n", setups, teardowns); 1672 total_failed = -1; 1673 } 1674 1675 free(test_states); 1676 free((void*)failed_names); 1677 1678 fail_if_blocks_allocated(check_point, "run_tests"); 1679 return (int)total_failed; 1680} 1681