2 * Copyright 2008 Google Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
34 #define vsnprintf _vsnprintf
37 * Backwards compatibility with headers shipped with Visual Studio 2005 and
40 WINBASEAPI BOOL WINAPI IsDebuggerPresent(VOID);
47 // Size of guard bytes around dynamically allocated blocks.
48 #define MALLOC_GUARD_SIZE 16
49 // Pattern used to initialize guard blocks.
50 #define MALLOC_GUARD_PATTERN 0xEF
51 // Pattern used to initialize memory allocated with test_malloc().
52 #define MALLOC_ALLOC_PATTERN 0xBA
53 #define MALLOC_FREE_PATTERN 0xCD
54 // Alignment of allocated blocks. NOTE: This must be base2.
55 #define MALLOC_ALIGNMENT sizeof(size_t)
57 // Printf formatting for source code locations.
58 #define SOURCE_LOCATION_FORMAT "%s:%d"
60 // Calculates the number of elements in an array.
61 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
63 // Declare and initialize the pointer member of ValuePointer variable name
65 #define declare_initialize_value_pointer_pointer(name, ptr) \
68 name.pointer = (void*)(ptr)
70 // Declare and initialize the value member of ValuePointer variable name
72 #define declare_initialize_value_pointer_value(name, val) \
76 // Cast a LargestIntegralType to pointer_type via a ValuePointer.
77 #define cast_largest_integral_type_to_pointer( \
78 pointer_type, largest_integral_type) \
79 ((pointer_type)((ValuePointer*)&(largest_integral_type))->pointer)
81 // Used to cast LargetIntegralType to void* and vice versa.
82 typedef union ValuePointer {
83 LargestIntegralType value;
87 // Doubly linked list node.
88 typedef struct ListNode {
91 struct ListNode *next;
92 struct ListNode *prev;
95 // Debug information for malloc().
96 typedef struct MallocBlockInfo {
97 void* block; // Address of the block returned by malloc().
98 size_t allocated_size; // Total size of the allocated block.
99 size_t size; // Request block size.
100 SourceLocation location; // Where the block was allocated.
101 ListNode node; // Node within list of all allocated blocks.
104 // State of each test.
105 typedef struct TestState {
106 const ListNode *check_point; // Check point of the test if there's a
108 void *state; // State associated with the test.
111 // Determines whether two values are the same.
112 typedef int (*EqualityFunction)(const void *left, const void *right);
114 // Value of a symbol and the place it was declared.
115 typedef struct SymbolValue {
116 SourceLocation location;
117 LargestIntegralType value;
120 /* Contains a list of values for a symbol.
121 * NOTE: Each structure referenced by symbol_values_list_head must have a
122 * SourceLocation as its' first member.
124 typedef struct SymbolMapValue {
125 const char *symbol_name;
126 ListNode symbol_values_list_head;
129 // Used by list_free() to deallocate values referenced by list nodes.
130 typedef void (*CleanupListValue)(const void *value, void *cleanup_value_data);
132 // Structure used to check the range of integer types.
133 typedef struct CheckIntegerRange {
134 CheckParameterEvent event;
135 LargestIntegralType minimum;
136 LargestIntegralType maximum;
139 // Structure used to check whether an integer value is in a set.
140 typedef struct CheckIntegerSet {
141 CheckParameterEvent event;
142 const LargestIntegralType *set;
146 /* Used to check whether a parameter matches the area of memory referenced by
148 typedef struct CheckMemoryData {
149 CheckParameterEvent event;
154 static ListNode* list_initialize(ListNode * const node);
155 static ListNode* list_add(ListNode * const head, ListNode *new_node);
156 static ListNode* list_add_value(ListNode * const head, const void *value,
158 static ListNode* list_remove(
159 ListNode * const node, const CleanupListValue cleanup_value,
160 void * const cleanup_value_data);
161 static void list_remove_free(
162 ListNode * const node, const CleanupListValue cleanup_value,
163 void * const cleanup_value_data);
164 static int list_empty(const ListNode * const head);
165 static int list_find(
166 ListNode * const head, const void *value,
167 const EqualityFunction equal_func, ListNode **output);
168 static int list_first(ListNode * const head, ListNode **output);
169 static ListNode* list_free(
170 ListNode * const head, const CleanupListValue cleanup_value,
171 void * const cleanup_value_data);
173 static void add_symbol_value(
174 ListNode * const symbol_map_head, const char * const symbol_names[],
175 const size_t number_of_symbol_names, const void* value, const int count);
176 static int get_symbol_value(
177 ListNode * const symbol_map_head, const char * const symbol_names[],
178 const size_t number_of_symbol_names, void **output);
179 static void free_value(const void *value, void *cleanup_value_data);
180 static void free_symbol_map_value(
181 const void *value, void *cleanup_value_data);
182 static void remove_always_return_values(ListNode * const map_head,
183 const size_t number_of_symbol_names);
184 static int check_for_leftover_values(
185 const ListNode * const map_head, const char * const error_message,
186 const size_t number_of_symbol_names);
187 // This must be called at the beginning of a test to initialize some data
189 static void initialize_testing(const char *test_name);
190 // This must be called at the end of a test to free() allocated structures.
191 static void teardown_testing(const char *test_name);
194 // Keeps track of the calling context returned by setenv() so that the fail()
195 // method can jump out of a test.
196 static jmp_buf global_run_test_env;
197 static int global_running_test = 0;
199 // Keeps track of the calling context returned by setenv() so that
200 // mock_assert() can optionally jump back to expect_assert_failure().
201 jmp_buf global_expect_assert_env;
202 int global_expecting_assert = 0;
204 // Keeps a map of the values that functions will have to return to provide
205 // mocked interfaces.
206 static ListNode global_function_result_map_head;
207 // Location of the last mock value returned was declared.
208 static SourceLocation global_last_mock_value_location;
210 /* Keeps a map of the values that functions expect as parameters to their
211 * mocked interfaces. */
212 static ListNode global_function_parameter_map_head;
213 // Location of last parameter value checked was declared.
214 static SourceLocation global_last_parameter_location;
216 // List of all currently allocated blocks.
217 static ListNode global_allocated_blocks;
220 // Signals caught by exception_handler().
221 static const int exception_signals[] = {
229 // Default signal functions that should be restored after a test is complete.
230 typedef void (*SignalFunction)(int signal);
231 static SignalFunction default_signal_functions[
232 ARRAY_LENGTH(exception_signals)];
236 // The default exception filter.
237 static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter;
240 typedef struct ExceptionCodeInfo {
242 const char* description;
245 #define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code}
247 static const ExceptionCodeInfo exception_codes[] = {
248 EXCEPTION_CODE_INFO(EXCEPTION_ACCESS_VIOLATION),
249 EXCEPTION_CODE_INFO(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),
250 EXCEPTION_CODE_INFO(EXCEPTION_DATATYPE_MISALIGNMENT),
251 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DENORMAL_OPERAND),
252 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DIVIDE_BY_ZERO),
253 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INEXACT_RESULT),
254 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INVALID_OPERATION),
255 EXCEPTION_CODE_INFO(EXCEPTION_FLT_OVERFLOW),
256 EXCEPTION_CODE_INFO(EXCEPTION_FLT_STACK_CHECK),
257 EXCEPTION_CODE_INFO(EXCEPTION_FLT_UNDERFLOW),
258 EXCEPTION_CODE_INFO(EXCEPTION_GUARD_PAGE),
259 EXCEPTION_CODE_INFO(EXCEPTION_ILLEGAL_INSTRUCTION),
260 EXCEPTION_CODE_INFO(EXCEPTION_INT_DIVIDE_BY_ZERO),
261 EXCEPTION_CODE_INFO(EXCEPTION_INT_OVERFLOW),
262 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_DISPOSITION),
263 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_HANDLE),
264 EXCEPTION_CODE_INFO(EXCEPTION_IN_PAGE_ERROR),
265 EXCEPTION_CODE_INFO(EXCEPTION_NONCONTINUABLE_EXCEPTION),
266 EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION),
267 EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW),
272 // Exit the currently executing test.
273 static void exit_test(const int quit_application) {
274 if (global_running_test) {
275 longjmp(global_run_test_env, 1);
276 } else if (quit_application) {
282 // Initialize a SourceLocation structure.
283 static void initialize_source_location(SourceLocation * const location) {
284 assert_non_null(location);
285 location->file = NULL;
290 // Determine whether a source location is currently set.
291 static int source_location_is_set(const SourceLocation * const location) {
292 assert_non_null(location);
293 return location->file && location->line;
297 // Set a source location.
298 static void set_source_location(
299 SourceLocation * const location, const char * const file,
301 assert_non_null(location);
302 location->file = file;
303 location->line = line;
307 // Create function results and expected parameter lists.
308 void initialize_testing(const char *test_name) {
310 list_initialize(&global_function_result_map_head);
311 initialize_source_location(&global_last_mock_value_location);
312 list_initialize(&global_function_parameter_map_head);
313 initialize_source_location(&global_last_parameter_location);
317 static void fail_if_leftover_values(const char *test_name) {
318 int error_occurred = 0;
320 remove_always_return_values(&global_function_result_map_head, 1);
321 if (check_for_leftover_values(
322 &global_function_result_map_head,
323 "%s() has remaining non-returned values.\n", 1)) {
327 remove_always_return_values(&global_function_parameter_map_head, 2);
328 if (check_for_leftover_values(
329 &global_function_parameter_map_head,
330 "%s parameter still has values that haven't been checked.\n", 2)) {
333 if (error_occurred) {
339 void teardown_testing(const char *test_name) {
341 list_free(&global_function_result_map_head, free_symbol_map_value,
343 initialize_source_location(&global_last_mock_value_location);
344 list_free(&global_function_parameter_map_head, free_symbol_map_value,
346 initialize_source_location(&global_last_parameter_location);
349 // Initialize a list node.
350 static ListNode* list_initialize(ListNode * const node) {
359 /* Adds a value at the tail of a given list.
360 * The node referencing the value is allocated from the heap. */
361 static ListNode* list_add_value(ListNode * const head, const void *value,
362 const int refcount) {
363 ListNode * const new_node = (ListNode*)malloc(sizeof(ListNode));
364 assert_non_null(head);
365 assert_non_null(value);
366 new_node->value = value;
367 new_node->refcount = refcount;
368 return list_add(head, new_node);
372 // Add new_node to the end of the list.
373 static ListNode* list_add(ListNode * const head, ListNode *new_node) {
374 assert_non_null(head);
375 assert_non_null(new_node);
376 new_node->next = head;
377 new_node->prev = head->prev;
378 head->prev->next = new_node;
379 head->prev = new_node;
384 // Remove a node from a list.
385 static ListNode* list_remove(
386 ListNode * const node, const CleanupListValue cleanup_value,
387 void * const cleanup_value_data) {
388 assert_non_null(node);
389 node->prev->next = node->next;
390 node->next->prev = node->prev;
392 cleanup_value(node->value, cleanup_value_data);
398 /* Remove a list node from a list and free the node. */
399 static void list_remove_free(
400 ListNode * const node, const CleanupListValue cleanup_value,
401 void * const cleanup_value_data) {
402 assert_non_null(node);
403 free(list_remove(node, cleanup_value, cleanup_value_data));
407 /* Frees memory kept by a linked list
408 * The cleanup_value function is called for every "value" field of nodes in the
409 * list, except for the head. In addition to each list value,
410 * cleanup_value_data is passed to each call to cleanup_value. The head
411 * of the list is not deallocated.
413 static ListNode* list_free(
414 ListNode * const head, const CleanupListValue cleanup_value,
415 void * const cleanup_value_data) {
416 assert_non_null(head);
417 while (!list_empty(head)) {
418 list_remove_free(head->next, cleanup_value, cleanup_value_data);
424 // Determine whether a list is empty.
425 static int list_empty(const ListNode * const head) {
426 assert_non_null(head);
427 return head->next == head;
431 /* Find a value in the list using the equal_func to compare each node with the
434 static int list_find(ListNode * const head, const void *value,
435 const EqualityFunction equal_func, ListNode **output) {
437 assert_non_null(head);
438 for (current = head->next; current != head; current = current->next) {
439 if (equal_func(current->value, value)) {
447 // Returns the first node of a list
448 static int list_first(ListNode * const head, ListNode **output) {
449 ListNode *target_node;
450 assert_non_null(head);
451 if (list_empty(head)) {
454 target_node = head->next;
455 *output = target_node;
460 // Deallocate a value referenced by a list.
461 static void free_value(const void *value, void *cleanup_value_data) {
462 (void)cleanup_value_data;
463 assert_non_null(value);
468 // Releases memory associated to a symbol_map_value.
469 static void free_symbol_map_value(const void *value,
470 void *cleanup_value_data) {
471 SymbolMapValue * const map_value = (SymbolMapValue*)value;
472 const LargestIntegralType children = cast_ptr_to_largest_integral_type(cleanup_value_data);
473 assert_non_null(value);
474 list_free(&map_value->symbol_values_list_head,
475 children ? free_symbol_map_value : free_value,
476 (void *) ((uintptr_t)children - 1));
481 /* Determine whether a symbol name referenced by a symbol_map_value
482 * matches the specified function name. */
483 static int symbol_names_match(const void *map_value, const void *symbol) {
484 return !strcmp(((SymbolMapValue*)map_value)->symbol_name,
485 (const char*)symbol);
489 /* Adds a value to the queue of values associated with the given
490 * hierarchy of symbols. It's assumed value is allocated from the heap.
492 static void add_symbol_value(ListNode * const symbol_map_head,
493 const char * const symbol_names[],
494 const size_t number_of_symbol_names,
495 const void* value, const int refcount) {
496 const char* symbol_name;
497 ListNode *target_node;
498 SymbolMapValue *target_map_value;
499 assert_non_null(symbol_map_head);
500 assert_non_null(symbol_names);
501 assert_true(number_of_symbol_names);
502 symbol_name = symbol_names[0];
504 if (!list_find(symbol_map_head, symbol_name, symbol_names_match,
506 SymbolMapValue * const new_symbol_map_value =
507 (SymbolMapValue*)malloc(sizeof(*new_symbol_map_value));
508 new_symbol_map_value->symbol_name = symbol_name;
509 list_initialize(&new_symbol_map_value->symbol_values_list_head);
510 target_node = list_add_value(symbol_map_head, new_symbol_map_value,
514 target_map_value = (SymbolMapValue*)target_node->value;
515 if (number_of_symbol_names == 1) {
516 list_add_value(&target_map_value->symbol_values_list_head,
519 add_symbol_value(&target_map_value->symbol_values_list_head,
520 &symbol_names[1], number_of_symbol_names - 1, value,
526 /* Gets the next value associated with the given hierarchy of symbols.
527 * The value is returned as an output parameter with the function returning the
528 * node's old refcount value if a value is found, 0 otherwise.
529 * This means that a return value of 1 indicates the node was just removed from
532 static int get_symbol_value(
533 ListNode * const head, const char * const symbol_names[],
534 const size_t number_of_symbol_names, void **output) {
535 const char* symbol_name;
536 ListNode *target_node;
537 assert_non_null(head);
538 assert_non_null(symbol_names);
539 assert_true(number_of_symbol_names);
540 assert_non_null(output);
541 symbol_name = symbol_names[0];
543 if (list_find(head, symbol_name, symbol_names_match, &target_node)) {
544 SymbolMapValue *map_value;
545 ListNode *child_list;
546 int return_value = 0;
547 assert_non_null(target_node);
548 assert_non_null(target_node->value);
550 map_value = (SymbolMapValue*)target_node->value;
551 child_list = &map_value->symbol_values_list_head;
553 if (number_of_symbol_names == 1) {
554 ListNode *value_node = NULL;
555 return_value = list_first(child_list, &value_node);
556 assert_true(return_value);
557 *output = (void*) value_node->value;
558 return_value = value_node->refcount;
559 if (--value_node->refcount == 0) {
560 list_remove_free(value_node, NULL, NULL);
563 return_value = get_symbol_value(
564 child_list, &symbol_names[1], number_of_symbol_names - 1,
567 if (list_empty(child_list)) {
568 list_remove_free(target_node, free_symbol_map_value, (void*)0);
572 print_error("No entries for symbol %s.\n", symbol_name);
578 /* Traverse down a tree of symbol values and remove the first symbol value
579 * in each branch that has a refcount < -1 (i.e should always be returned
580 * and has been returned at least once).
582 static void remove_always_return_values(ListNode * const map_head,
583 const size_t number_of_symbol_names) {
585 assert_non_null(map_head);
586 assert_true(number_of_symbol_names);
587 current = map_head->next;
588 while (current != map_head) {
589 SymbolMapValue * const value = (SymbolMapValue*)current->value;
590 ListNode * const next = current->next;
591 ListNode *child_list;
592 assert_non_null(value);
593 child_list = &value->symbol_values_list_head;
595 if (!list_empty(child_list)) {
596 if (number_of_symbol_names == 1) {
597 ListNode * const child_node = child_list->next;
598 // If this item has been returned more than once, free it.
599 if (child_node->refcount < -1) {
600 list_remove_free(child_node, free_value, NULL);
603 remove_always_return_values(child_list,
604 number_of_symbol_names - 1);
608 if (list_empty(child_list)) {
609 list_remove_free(current, free_value, NULL);
615 /* Checks if there are any leftover values set up by the test that were never
616 * retrieved through execution, and fail the test if that is the case.
618 static int check_for_leftover_values(
619 const ListNode * const map_head, const char * const error_message,
620 const size_t number_of_symbol_names) {
621 const ListNode *current;
622 int symbols_with_leftover_values = 0;
623 assert_non_null(map_head);
624 assert_true(number_of_symbol_names);
626 for (current = map_head->next; current != map_head;
627 current = current->next) {
628 const SymbolMapValue * const value =
629 (SymbolMapValue*)current->value;
630 const ListNode *child_list;
631 assert_non_null(value);
632 child_list = &value->symbol_values_list_head;
634 if (!list_empty(child_list)) {
635 if (number_of_symbol_names == 1) {
636 const ListNode *child_node;
637 print_error(error_message, value->symbol_name);
638 print_error(" Remaining item(s) declared at...\n");
640 for (child_node = child_list->next; child_node != child_list;
641 child_node = child_node->next) {
642 const SourceLocation * const location =
643 (const SourceLocation*)child_node->value;
644 print_error(" " SOURCE_LOCATION_FORMAT "\n",
645 location->file, location->line);
648 print_error("%s.", value->symbol_name);
649 check_for_leftover_values(child_list, error_message,
650 number_of_symbol_names - 1);
652 symbols_with_leftover_values ++;
655 return symbols_with_leftover_values;
659 // Get the next return value for the specified mock function.
660 LargestIntegralType _mock(const char * const function, const char* const file,
663 const int rc = get_symbol_value(&global_function_result_map_head,
664 &function, 1, &result);
666 SymbolValue * const symbol = (SymbolValue*)result;
667 const LargestIntegralType value = symbol->value;
668 global_last_mock_value_location = symbol->location;
674 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
675 "to mock function %s\n", file, line, function);
676 if (source_location_is_set(&global_last_mock_value_location)) {
677 print_error("Previously returned mock value was declared at "
678 SOURCE_LOCATION_FORMAT "\n",
679 global_last_mock_value_location.file,
680 global_last_mock_value_location.line);
682 print_error("There were no previously returned mock values for "
691 // Add a return value for the specified mock function name.
692 void _will_return(const char * const function_name, const char * const file,
693 const int line, const LargestIntegralType value,
695 SymbolValue * const return_value =
696 (SymbolValue*)malloc(sizeof(*return_value));
697 assert_true(count > 0 || count == -1);
698 return_value->value = value;
699 set_source_location(&return_value->location, file, line);
700 add_symbol_value(&global_function_result_map_head, &function_name, 1,
701 return_value, count);
705 /* Add a custom parameter checking function. If the event parameter is NULL
706 * the event structure is allocated internally by this function. If event
707 * parameter is provided it must be allocated on the heap and doesn't need to
708 * be deallocated by the caller.
711 const char* const function, const char* const parameter,
712 const char* const file, const int line,
713 const CheckParameterValue check_function,
714 const LargestIntegralType check_data,
715 CheckParameterEvent * const event, const int count) {
716 CheckParameterEvent * const check =
717 event ? event : (CheckParameterEvent*)malloc(sizeof(*check));
718 const char* symbols[] = {function, parameter};
719 check->parameter_name = parameter;
720 check->check_value = check_function;
721 check->check_value_data = check_data;
722 set_source_location(&check->location, file, line);
723 add_symbol_value(&global_function_parameter_map_head, symbols, 2, check,
728 /* Returns 1 if the specified values are equal. If the values are not equal
729 * an error is displayed and 0 is returned. */
730 static int values_equal_display_error(const LargestIntegralType left,
731 const LargestIntegralType right) {
732 const int equal = left == right;
734 print_error(LargestIntegralTypePrintfFormat " != "
735 LargestIntegralTypePrintfFormat "\n", left, right);
740 /* Returns 1 if the specified values are not equal. If the values are equal
741 * an error is displayed and 0 is returned. */
742 static int values_not_equal_display_error(const LargestIntegralType left,
743 const LargestIntegralType right) {
744 const int not_equal = left != right;
746 print_error(LargestIntegralTypePrintfFormat " == "
747 LargestIntegralTypePrintfFormat "\n", left, right);
753 /* Determine whether value is contained within check_integer_set.
754 * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is
755 * returned and an error is displayed. If invert is 1 and the value is not
756 * in the set 1 is returned, otherwise 0 is returned and an error is
758 static int value_in_set_display_error(
759 const LargestIntegralType value,
760 const CheckIntegerSet * const check_integer_set, const int invert) {
761 int succeeded = invert;
762 assert_non_null(check_integer_set);
764 const LargestIntegralType * const set = check_integer_set->set;
765 const size_t size_of_set = check_integer_set->size_of_set;
767 for (i = 0; i < size_of_set; i++) {
768 if (set[i] == value) {
769 // If invert = 0 and item is found, succeeded = 1.
770 // If invert = 1 and item is found, succeeded = 0.
771 succeeded = !succeeded;
778 print_error("%d is %sin the set (", value, invert ? "" : "not ");
779 for (i = 0; i < size_of_set; i++) {
780 print_error("%d, ", set[i]);
788 /* Determine whether a value is within the specified range. If the value is
789 * within the specified range 1 is returned. If the value isn't within the
790 * specified range an error is displayed and 0 is returned. */
791 static int integer_in_range_display_error(
792 const LargestIntegralType value, const LargestIntegralType range_min,
793 const LargestIntegralType range_max) {
794 if (value >= range_min && value <= range_max) {
797 print_error("%d is not within the range %d-%d\n", value, range_min,
803 /* Determine whether a value is within the specified range. If the value
804 * is not within the range 1 is returned. If the value is within the
805 * specified range an error is displayed and zero is returned. */
806 static int integer_not_in_range_display_error(
807 const LargestIntegralType value, const LargestIntegralType range_min,
808 const LargestIntegralType range_max) {
809 if (value < range_min || value > range_max) {
812 print_error("%d is within the range %d-%d\n", value, range_min,
818 /* Determine whether the specified strings are equal. If the strings are equal
819 * 1 is returned. If they're not equal an error is displayed and 0 is
821 static int string_equal_display_error(
822 const char * const left, const char * const right) {
823 if (strcmp(left, right) == 0) {
826 print_error("\"%s\" != \"%s\"\n", left, right);
831 /* Determine whether the specified strings are equal. If the strings are not
832 * equal 1 is returned. If they're not equal an error is displayed and 0 is
834 static int string_not_equal_display_error(
835 const char * const left, const char * const right) {
836 if (strcmp(left, right) != 0) {
839 print_error("\"%s\" == \"%s\"\n", left, right);
844 /* Determine whether the specified areas of memory are equal. If they're equal
845 * 1 is returned otherwise an error is displayed and 0 is returned. */
846 static int memory_equal_display_error(const char* const a, const char* const b,
850 for (i = 0; i < size; i++) {
854 print_error("difference at offset %d 0x%02x 0x%02x\n", i, l, r);
859 print_error("%d bytes of 0x%08x and 0x%08x differ\n", differences,
867 /* Determine whether the specified areas of memory are not equal. If they're
868 * not equal 1 is returned otherwise an error is displayed and 0 is
870 static int memory_not_equal_display_error(
871 const char* const a, const char* const b, const size_t size) {
874 for (i = 0; i < size; i++) {
882 print_error("%u bytes of 0x%08x and 0x%08x the same\n", same,
890 // CheckParameterValue callback to check whether a value is within a set.
891 static int check_in_set(const LargestIntegralType value,
892 const LargestIntegralType check_value_data) {
893 return value_in_set_display_error(value,
894 cast_largest_integral_type_to_pointer(CheckIntegerSet*,
895 check_value_data), 0);
899 // CheckParameterValue callback to check whether a value isn't within a set.
900 static int check_not_in_set(const LargestIntegralType value,
901 const LargestIntegralType check_value_data) {
902 return value_in_set_display_error(value,
903 cast_largest_integral_type_to_pointer(CheckIntegerSet*,
904 check_value_data), 1);
908 /* Create the callback data for check_in_set() or check_not_in_set() and
909 * register a check event. */
910 static void expect_set(
911 const char* const function, const char* const parameter,
912 const char* const file, const int line,
913 const LargestIntegralType values[], const size_t number_of_values,
914 const CheckParameterValue check_function, const int count) {
915 CheckIntegerSet * const check_integer_set =
916 (CheckIntegerSet*)malloc(sizeof(*check_integer_set) +
917 (sizeof(values[0]) * number_of_values));
918 LargestIntegralType * const set = (LargestIntegralType*)(
919 check_integer_set + 1);
920 declare_initialize_value_pointer_pointer(check_data, check_integer_set);
921 assert_non_null(values);
922 assert_true(number_of_values);
923 memcpy(set, values, number_of_values * sizeof(values[0]));
924 check_integer_set->set = set;
926 function, parameter, file, line, check_function,
927 check_data.value, &check_integer_set->event, count);
931 // Add an event to check whether a value is in a set.
933 const char* const function, const char* const parameter,
934 const char* const file, const int line,
935 const LargestIntegralType values[], const size_t number_of_values,
937 expect_set(function, parameter, file, line, values, number_of_values,
938 check_in_set, count);
942 // Add an event to check whether a value isn't in a set.
943 void _expect_not_in_set(
944 const char* const function, const char* const parameter,
945 const char* const file, const int line,
946 const LargestIntegralType values[], const size_t number_of_values,
948 expect_set(function, parameter, file, line, values, number_of_values,
949 check_not_in_set, count);
953 // CheckParameterValue callback to check whether a value is within a range.
954 static int check_in_range(const LargestIntegralType value,
955 const LargestIntegralType check_value_data) {
956 CheckIntegerRange * const check_integer_range =
957 cast_largest_integral_type_to_pointer(CheckIntegerRange*,
959 assert_non_null(check_integer_range);
960 return integer_in_range_display_error(value, check_integer_range->minimum,
961 check_integer_range->maximum);
965 // CheckParameterValue callback to check whether a value is not within a range.
966 static int check_not_in_range(const LargestIntegralType value,
967 const LargestIntegralType check_value_data) {
968 CheckIntegerRange * const check_integer_range =
969 cast_largest_integral_type_to_pointer(CheckIntegerRange*,
971 assert_non_null(check_integer_range);
972 return integer_not_in_range_display_error(
973 value, check_integer_range->minimum, check_integer_range->maximum);
977 /* Create the callback data for check_in_range() or check_not_in_range() and
978 * register a check event. */
979 static void expect_range(
980 const char* const function, const char* const parameter,
981 const char* const file, const int line,
982 const LargestIntegralType minimum, const LargestIntegralType maximum,
983 const CheckParameterValue check_function, const int count) {
984 CheckIntegerRange * const check_integer_range =
985 (CheckIntegerRange*)malloc(sizeof(*check_integer_range));
986 declare_initialize_value_pointer_pointer(check_data, check_integer_range);
987 check_integer_range->minimum = minimum;
988 check_integer_range->maximum = maximum;
989 _expect_check(function, parameter, file, line, check_function,
990 check_data.value, &check_integer_range->event, count);
994 // Add an event to determine whether a parameter is within a range.
995 void _expect_in_range(
996 const char* const function, const char* const parameter,
997 const char* const file, const int line,
998 const LargestIntegralType minimum, const LargestIntegralType maximum,
1000 expect_range(function, parameter, file, line, minimum, maximum,
1001 check_in_range, count);
1005 // Add an event to determine whether a parameter is not within a range.
1006 void _expect_not_in_range(
1007 const char* const function, const char* const parameter,
1008 const char* const file, const int line,
1009 const LargestIntegralType minimum, const LargestIntegralType maximum,
1011 expect_range(function, parameter, file, line, minimum, maximum,
1012 check_not_in_range, count);
1016 /* CheckParameterValue callback to check whether a value is equal to an
1017 * expected value. */
1018 static int check_value(const LargestIntegralType value,
1019 const LargestIntegralType check_value_data) {
1020 return values_equal_display_error(value, check_value_data);
1024 // Add an event to check a parameter equals an expected value.
1026 const char* const function, const char* const parameter,
1027 const char* const file, const int line,
1028 const LargestIntegralType value, const int count) {
1029 _expect_check(function, parameter, file, line, check_value, value, NULL,
1034 /* CheckParameterValue callback to check whether a value is not equal to an
1035 * expected value. */
1036 static int check_not_value(const LargestIntegralType value,
1037 const LargestIntegralType check_value_data) {
1038 return values_not_equal_display_error(value, check_value_data);
1042 // Add an event to check a parameter is not equal to an expected value.
1043 void _expect_not_value(
1044 const char* const function, const char* const parameter,
1045 const char* const file, const int line,
1046 const LargestIntegralType value, const int count) {
1047 _expect_check(function, parameter, file, line, check_not_value, value,
1052 // CheckParameterValue callback to check whether a parameter equals a string.
1053 static int check_string(const LargestIntegralType value,
1054 const LargestIntegralType check_value_data) {
1055 return string_equal_display_error(
1056 cast_largest_integral_type_to_pointer(char*, value),
1057 cast_largest_integral_type_to_pointer(char*, check_value_data));
1061 // Add an event to check whether a parameter is equal to a string.
1062 void _expect_string(
1063 const char* const function, const char* const parameter,
1064 const char* const file, const int line, const char* string,
1066 declare_initialize_value_pointer_pointer(string_pointer, (char*)string);
1067 _expect_check(function, parameter, file, line, check_string,
1068 string_pointer.value, NULL, count);
1072 /* CheckParameterValue callback to check whether a parameter is not equals to
1074 static int check_not_string(const LargestIntegralType value,
1075 const LargestIntegralType check_value_data) {
1076 return string_not_equal_display_error(
1077 cast_largest_integral_type_to_pointer(char*, value),
1078 cast_largest_integral_type_to_pointer(char*, check_value_data));
1082 // Add an event to check whether a parameter is not equal to a string.
1083 void _expect_not_string(
1084 const char* const function, const char* const parameter,
1085 const char* const file, const int line, const char* string,
1087 declare_initialize_value_pointer_pointer(string_pointer, (char*)string);
1088 _expect_check(function, parameter, file, line, check_not_string,
1089 string_pointer.value, NULL, count);
1092 /* CheckParameterValue callback to check whether a parameter equals an area of
1094 static int check_memory(const LargestIntegralType value,
1095 const LargestIntegralType check_value_data) {
1096 CheckMemoryData * const check = cast_largest_integral_type_to_pointer(
1097 CheckMemoryData*, check_value_data);
1098 assert_non_null(check);
1099 return memory_equal_display_error(
1100 cast_largest_integral_type_to_pointer(const char*, value),
1101 (const char*)check->memory, check->size);
1105 /* Create the callback data for check_memory() or check_not_memory() and
1106 * register a check event. */
1107 static void expect_memory_setup(
1108 const char* const function, const char* const parameter,
1109 const char* const file, const int line,
1110 const void * const memory, const size_t size,
1111 const CheckParameterValue check_function, const int count) {
1112 CheckMemoryData * const check_data =
1113 (CheckMemoryData*)malloc(sizeof(*check_data) + size);
1114 void * const mem = (void*)(check_data + 1);
1115 declare_initialize_value_pointer_pointer(check_data_pointer, check_data);
1116 assert_non_null(memory);
1118 memcpy(mem, memory, size);
1119 check_data->memory = mem;
1120 check_data->size = size;
1121 _expect_check(function, parameter, file, line, check_function,
1122 check_data_pointer.value, &check_data->event, count);
1126 // Add an event to check whether a parameter matches an area of memory.
1127 void _expect_memory(
1128 const char* const function, const char* const parameter,
1129 const char* const file, const int line, const void* const memory,
1130 const size_t size, const int count) {
1131 expect_memory_setup(function, parameter, file, line, memory, size,
1132 check_memory, count);
1136 /* CheckParameterValue callback to check whether a parameter is not equal to
1137 * an area of memory. */
1138 static int check_not_memory(const LargestIntegralType value,
1139 const LargestIntegralType check_value_data) {
1140 CheckMemoryData * const check = cast_largest_integral_type_to_pointer(
1141 CheckMemoryData*, check_value_data);
1142 assert_non_null(check);
1143 return memory_not_equal_display_error(
1144 cast_largest_integral_type_to_pointer(const char*, value),
1145 (const char*)check->memory,
1150 // Add an event to check whether a parameter doesn't match an area of memory.
1151 void _expect_not_memory(
1152 const char* const function, const char* const parameter,
1153 const char* const file, const int line, const void* const memory,
1154 const size_t size, const int count) {
1155 expect_memory_setup(function, parameter, file, line, memory, size,
1156 check_not_memory, count);
1160 // CheckParameterValue callback that always returns 1.
1161 static int check_any(const LargestIntegralType value,
1162 const LargestIntegralType check_value_data) {
1164 (void)check_value_data;
1169 // Add an event to allow any value for a parameter.
1171 const char* const function, const char* const parameter,
1172 const char* const file, const int line, const int count) {
1173 _expect_check(function, parameter, file, line, check_any, 0, NULL,
1178 void _check_expected(
1179 const char * const function_name, const char * const parameter_name,
1180 const char* file, const int line, const LargestIntegralType value) {
1182 const char* symbols[] = {function_name, parameter_name};
1183 const int rc = get_symbol_value(&global_function_parameter_map_head,
1184 symbols, 2, &result);
1186 CheckParameterEvent * const check = (CheckParameterEvent*)result;
1187 int check_succeeded;
1188 global_last_parameter_location = check->location;
1189 check_succeeded = check->check_value(value, check->check_value_data);
1193 if (!check_succeeded) {
1194 print_error("ERROR: Check of parameter %s, function %s failed\n"
1195 "Expected parameter declared at "
1196 SOURCE_LOCATION_FORMAT "\n",
1197 parameter_name, function_name,
1198 global_last_parameter_location.file,
1199 global_last_parameter_location.line);
1203 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
1204 "to check parameter %s of function %s\n", file, line,
1205 parameter_name, function_name);
1206 if (source_location_is_set(&global_last_parameter_location)) {
1207 print_error("Previously declared parameter value was declared at "
1208 SOURCE_LOCATION_FORMAT "\n",
1209 global_last_parameter_location.file,
1210 global_last_parameter_location.line);
1212 print_error("There were no previously declared parameter values "
1213 "for this test.\n");
1220 // Replacement for assert.
1221 void mock_assert(const int result, const char* const expression,
1222 const char* const file, const int line) {
1224 if (global_expecting_assert) {
1225 longjmp(global_expect_assert_env, (int)expression);
1227 print_error("ASSERT: %s\n", expression);
1234 void _assert_true(const LargestIntegralType result,
1235 const char * const expression,
1236 const char * const file, const int line) {
1238 print_error("%s\n", expression);
1243 void _assert_int_equal(
1244 const LargestIntegralType a, const LargestIntegralType b,
1245 const char * const file, const int line) {
1246 if (!values_equal_display_error(a, b)) {
1252 void _assert_int_not_equal(
1253 const LargestIntegralType a, const LargestIntegralType b,
1254 const char * const file, const int line) {
1255 if (!values_not_equal_display_error(a, b)) {
1261 void _assert_string_equal(const char * const a, const char * const b,
1262 const char * const file, const int line) {
1263 if (!string_equal_display_error(a, b)) {
1269 void _assert_string_not_equal(const char * const a, const char * const b,
1270 const char *file, const int line) {
1271 if (!string_not_equal_display_error(a, b)) {
1277 void _assert_memory_equal(const void * const a, const void * const b,
1278 const size_t size, const char* const file,
1280 if (!memory_equal_display_error((const char*)a, (const char*)b, size)) {
1286 void _assert_memory_not_equal(const void * const a, const void * const b,
1287 const size_t size, const char* const file,
1289 if (!memory_not_equal_display_error((const char*)a, (const char*)b,
1296 void _assert_in_range(
1297 const LargestIntegralType value, const LargestIntegralType minimum,
1298 const LargestIntegralType maximum, const char* const file,
1300 if (!integer_in_range_display_error(value, minimum, maximum)) {
1305 void _assert_not_in_range(
1306 const LargestIntegralType value, const LargestIntegralType minimum,
1307 const LargestIntegralType maximum, const char* const file,
1309 if (!integer_not_in_range_display_error(value, minimum, maximum)) {
1314 void _assert_in_set(const LargestIntegralType value,
1315 const LargestIntegralType values[],
1316 const size_t number_of_values, const char* const file,
1318 CheckIntegerSet check_integer_set;
1319 check_integer_set.set = values;
1320 check_integer_set.size_of_set = number_of_values;
1321 if (!value_in_set_display_error(value, &check_integer_set, 0)) {
1326 void _assert_not_in_set(const LargestIntegralType value,
1327 const LargestIntegralType values[],
1328 const size_t number_of_values, const char* const file,
1330 CheckIntegerSet check_integer_set;
1331 check_integer_set.set = values;
1332 check_integer_set.size_of_set = number_of_values;
1333 if (!value_in_set_display_error(value, &check_integer_set, 1)) {
1339 // Get the list of allocated blocks.
1340 static ListNode* get_allocated_blocks_list() {
1341 // If it initialized, initialize the list of allocated blocks.
1342 if (!global_allocated_blocks.value) {
1343 list_initialize(&global_allocated_blocks);
1344 global_allocated_blocks.value = (void*)1;
1346 return &global_allocated_blocks;
1349 // Use the real malloc in this function.
1351 void* _test_malloc(const size_t size, const char* file, const int line) {
1353 MallocBlockInfo *block_info;
1354 ListNode * const block_list = get_allocated_blocks_list();
1355 const size_t allocate_size = size + (MALLOC_GUARD_SIZE * 2) +
1356 sizeof(*block_info) + MALLOC_ALIGNMENT;
1357 char* const block = (char*)malloc(allocate_size);
1358 assert_non_null(block);
1360 // Calculate the returned address.
1361 ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE + sizeof(*block_info) +
1362 MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1));
1364 // Initialize the guard blocks.
1365 memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
1366 memset(ptr + size, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
1367 memset(ptr, MALLOC_ALLOC_PATTERN, size);
1369 block_info = (MallocBlockInfo*)(ptr - (MALLOC_GUARD_SIZE +
1370 sizeof(*block_info)));
1371 set_source_location(&block_info->location, file, line);
1372 block_info->allocated_size = allocate_size;
1373 block_info->size = size;
1374 block_info->block = block;
1375 block_info->node.value = block_info;
1376 list_add(block_list, &block_info->node);
1379 #define malloc test_malloc
1382 void* _test_calloc(const size_t number_of_elements, const size_t size,
1383 const char* file, const int line) {
1384 void* const ptr = _test_malloc(number_of_elements * size, file, line);
1386 memset(ptr, 0, number_of_elements * size);
1392 // Use the real free in this function.
1394 void _test_free(void* const ptr, const char* file, const int line) {
1396 char *block = (char*)ptr;
1397 MallocBlockInfo *block_info;
1398 _assert_true(cast_ptr_to_largest_integral_type(ptr), "ptr", file, line);
1399 block_info = (MallocBlockInfo*)(block - (MALLOC_GUARD_SIZE +
1400 sizeof(*block_info)));
1401 // Check the guard blocks.
1403 char *guards[2] = {block - MALLOC_GUARD_SIZE,
1404 block + block_info->size};
1405 for (i = 0; i < ARRAY_LENGTH(guards); i++) {
1407 char * const guard = guards[i];
1408 for (j = 0; j < MALLOC_GUARD_SIZE; j++) {
1409 const char diff = guard[j] - MALLOC_GUARD_PATTERN;
1412 "Guard block of 0x%08x size=%d allocated by "
1413 SOURCE_LOCATION_FORMAT " at 0x%08x is corrupt\n",
1414 (size_t)ptr, block_info->size,
1415 block_info->location.file, block_info->location.line,
1422 list_remove(&block_info->node, NULL, NULL);
1424 block = (char*)block_info->block;
1425 memset(block, MALLOC_FREE_PATTERN, block_info->allocated_size);
1428 #define free test_free
1431 // Crudely checkpoint the current heap state.
1432 static const ListNode* check_point_allocated_blocks() {
1433 return get_allocated_blocks_list()->prev;
1437 /* Display the blocks allocated after the specified check point. This
1438 * function returns the number of blocks displayed. */
1439 static int display_allocated_blocks(const ListNode * const check_point) {
1440 const ListNode * const head = get_allocated_blocks_list();
1441 const ListNode *node;
1442 int allocated_blocks = 0;
1443 assert_non_null(check_point);
1444 assert_non_null(check_point->next);
1446 for (node = check_point->next; node != head; node = node->next) {
1447 const MallocBlockInfo * const block_info =
1448 (const MallocBlockInfo*)node->value;
1449 assert_non_null(block_info);
1451 if (!allocated_blocks) {
1452 print_error("Blocks allocated...\n");
1454 print_error(" 0x%08x : " SOURCE_LOCATION_FORMAT "\n",
1455 block_info->block, block_info->location.file,
1456 block_info->location.line);
1457 allocated_blocks ++;
1459 return allocated_blocks;
1463 // Free all blocks allocated after the specified check point.
1464 static void free_allocated_blocks(const ListNode * const check_point) {
1465 const ListNode * const head = get_allocated_blocks_list();
1466 const ListNode *node;
1467 assert_non_null(check_point);
1469 node = check_point->next;
1470 assert_non_null(node);
1472 while (node != head) {
1473 MallocBlockInfo * const block_info = (MallocBlockInfo*)node->value;
1475 free((char*)block_info + sizeof(*block_info) + MALLOC_GUARD_SIZE);
1480 // Fail if any any blocks are allocated after the specified check point.
1481 static void fail_if_blocks_allocated(const ListNode * const check_point,
1482 const char * const test_name) {
1483 const int allocated_blocks = display_allocated_blocks(check_point);
1484 if (allocated_blocks) {
1485 free_allocated_blocks(check_point);
1486 print_error("ERROR: %s leaked %d block(s)\n", test_name,
1493 void _fail(const char * const file, const int line) {
1494 print_error("ERROR: " SOURCE_LOCATION_FORMAT " Failure!\n", file, line);
1500 static void exception_handler(int sig) {
1502 print_error("%d\n", sig);
1504 print_error("%s\n", strsignal(sig));
1511 static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
1512 EXCEPTION_RECORD * const exception_record =
1513 exception_pointers->ExceptionRecord;
1514 const DWORD code = exception_record->ExceptionCode;
1516 for (i = 0; i < ARRAY_LENGTH(exception_codes); i++) {
1517 const ExceptionCodeInfo * const code_info = &exception_codes[i];
1518 if (code == code_info->code) {
1519 static int shown_debug_message = 0;
1521 print_error("%s occurred at 0x%08x.\n", code_info->description,
1522 exception_record->ExceptionAddress);
1523 if (!shown_debug_message) {
1526 "To debug in Visual Studio...\n"
1527 "1. Select menu item File->Open Project\n"
1528 "2. Change 'Files of type' to 'Executable Files'\n"
1529 "3. Open this executable.\n"
1530 "4. Select menu item Debug->Start\n"
1532 "Alternatively, set the environment variable \n"
1533 "UNIT_TESTING_DEBUG to 1 and rebuild this executable, \n"
1534 "then click 'Debug' in the popup dialog box.\n"
1536 shown_debug_message = 1;
1539 return EXCEPTION_EXECUTE_HANDLER;
1542 return EXCEPTION_CONTINUE_SEARCH;
1547 // Standard output and error print methods.
1548 void vprint_message(const char* const format, va_list args) {
1550 vsnprintf(buffer, sizeof(buffer), format, args);
1551 printf("%s", buffer);
1554 OutputDebugString(buffer);
1559 void vprint_error(const char* const format, va_list args) {
1561 vsnprintf(buffer, sizeof(buffer), format, args);
1562 fprintf(stderr, "%s", buffer);
1565 OutputDebugString(buffer);
1570 void print_message(const char* const format, ...) {
1572 va_start(args, format);
1573 vprint_message(format, args);
1578 void print_error(const char* const format, ...) {
1580 va_start(args, format);
1581 vprint_error(format, args);
1587 const char * const function_name, const UnitTestFunction Function,
1588 void ** const volatile state, const UnitTestFunctionType function_type,
1589 const void* const heap_check_point) {
1590 const ListNode * const volatile check_point = (const ListNode*)
1592 heap_check_point : check_point_allocated_blocks());
1593 void *current_state = NULL;
1594 volatile int rc = 1;
1595 int handle_exceptions = 1;
1597 handle_exceptions = !IsDebuggerPresent();
1599 #if UNIT_TESTING_DEBUG
1600 handle_exceptions = 0;
1601 #endif // UNIT_TESTING_DEBUG
1603 if (handle_exceptions) {
1606 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
1607 default_signal_functions[i] = signal(
1608 exception_signals[i], exception_handler);
1611 previous_exception_filter = SetUnhandledExceptionFilter(
1616 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
1617 print_message("[ RUN ] %s\n", function_name);
1619 initialize_testing(function_name);
1620 global_running_test = 1;
1621 if (setjmp(global_run_test_env) == 0) {
1622 Function(state ? state : ¤t_state);
1623 fail_if_leftover_values(function_name);
1625 /* If this is a setup function then ignore any allocated blocks
1626 * only ensure they're deallocated on tear down. */
1627 if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) {
1628 fail_if_blocks_allocated(check_point, function_name);
1631 global_running_test = 0;
1633 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
1634 print_message("[ OK ] %s\n", function_name);
1638 global_running_test = 0;
1639 print_message("[ FAILED ] %s\n", function_name);
1641 teardown_testing(function_name);
1643 if (handle_exceptions) {
1646 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
1647 signal(exception_signals[i], default_signal_functions[i]);
1650 if (previous_exception_filter) {
1651 SetUnhandledExceptionFilter(previous_exception_filter);
1652 previous_exception_filter = NULL;
1661 int _run_tests(const UnitTest * const tests, const size_t number_of_tests) {
1662 // Whether to execute the next test.
1663 int run_next_test = 1;
1664 // Whether the previous test failed.
1665 int previous_test_failed = 0;
1666 // Check point of the heap state.
1667 const ListNode * const check_point = check_point_allocated_blocks();
1668 // Current test being executed.
1669 size_t current_test = 0;
1670 // Number of tests executed.
1671 size_t tests_executed = 0;
1672 // Number of failed tests.
1673 size_t total_failed = 0;
1674 // Number of setup functions.
1676 // Number of teardown functions.
1677 size_t teardowns = 0;
1678 /* A stack of test states. A state is pushed on the stack
1679 * when a test setup occurs and popped on tear down. */
1680 TestState* test_states =
1681 (TestState*)malloc(number_of_tests * sizeof(*test_states));
1682 size_t number_of_test_states = 0;
1683 // Names of the tests that failed.
1684 const char** failed_names = (const char**)malloc(number_of_tests *
1685 sizeof(*failed_names));
1686 void **current_state = NULL;
1688 print_message("[==========] Running %d test(s).\n", number_of_tests);
1690 // Make sure LargestIntegralType is at least the size of a pointer.
1691 assert_true(sizeof(LargestIntegralType) >= sizeof(void*));
1693 while (current_test < number_of_tests) {
1694 const ListNode *test_check_point = NULL;
1695 TestState *current_TestState;
1696 const UnitTest * const test = &tests[current_test++];
1697 if (!test->function) {
1701 switch (test->function_type) {
1702 case UNIT_TEST_FUNCTION_TYPE_TEST:
1705 case UNIT_TEST_FUNCTION_TYPE_SETUP: {
1706 // Checkpoint the heap before the setup.
1707 current_TestState = &test_states[number_of_test_states++];
1708 current_TestState->check_point = check_point_allocated_blocks();
1709 test_check_point = current_TestState->check_point;
1710 current_state = ¤t_TestState->state;
1711 *current_state = NULL;
1716 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
1717 // Check the heap based on the last setup checkpoint.
1718 assert_true(number_of_test_states);
1719 current_TestState = &test_states[--number_of_test_states];
1720 test_check_point = current_TestState->check_point;
1721 current_state = ¤t_TestState->state;
1725 print_error("Invalid unit test function type %d\n",
1726 test->function_type);
1731 if (run_next_test) {
1732 int failed = _run_test(test->name, test->function, current_state,
1733 test->function_type, test_check_point);
1735 failed_names[total_failed] = test->name;
1738 switch (test->function_type) {
1739 case UNIT_TEST_FUNCTION_TYPE_TEST:
1740 previous_test_failed = failed;
1741 total_failed += failed;
1745 case UNIT_TEST_FUNCTION_TYPE_SETUP:
1749 // Skip forward until the next test or setup function.
1752 previous_test_failed = 0;
1755 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
1756 // If this test failed.
1757 if (failed && !previous_test_failed) {
1763 assert_null("BUG: shouldn't be here!");
1770 print_message("[==========] %d test(s) run.\n", tests_executed);
1771 print_error("[ PASSED ] %d test(s).\n", tests_executed - total_failed);
1775 print_error("[ FAILED ] %d test(s), listed below:\n", total_failed);
1776 for (i = 0; i < total_failed; i++) {
1777 print_error("[ FAILED ] %s\n", failed_names[i]);
1780 print_error("\n %d FAILED TEST(S)\n", total_failed);
1783 if (number_of_test_states) {
1784 print_error("[ ERROR ] Mismatched number of setup %d and "
1785 "teardown %d functions\n", setups, teardowns);
1786 total_failed = (size_t)-1;
1790 free((void*)failed_names);
1792 fail_if_blocks_allocated(check_point, "run_tests");
1793 return (int)total_failed;