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.
32 #define vsnprintf _vsnprintf
35 // Size of guard bytes around dynamically allocated blocks.
36 #define MALLOC_GUARD_SIZE 16
37 // Pattern used to initialize guard blocks.
38 #define MALLOC_GUARD_PATTERN 0xEF
39 // Pattern used to initialize memory allocated with test_malloc().
40 #define MALLOC_ALLOC_PATTERN 0xBA
41 #define MALLOC_FREE_PATTERN 0xCD
42 // Alignment of allocated blocks. NOTE: This must be base2.
43 #define MALLOC_ALIGNMENT sizeof(size_t)
45 // Printf formatting for source code locations.
46 #define SOURCE_LOCATION_FORMAT "%s:%d"
48 // Calculates the number of elements in an array.
49 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
51 // Doubly linked list node.
52 typedef struct ListNode {
55 struct ListNode *next;
56 struct ListNode *prev;
59 // Debug information for malloc().
60 typedef struct MallocBlockInfo {
61 void* block; // Address of the block returned by malloc().
62 size_t allocated_size; // Total size of the allocated block.
63 size_t size; // Request block size.
64 SourceLocation location; // Where the block was allocated.
65 ListNode node; // Node within list of all allocated blocks.
68 // State of each test.
69 typedef struct TestState {
70 const ListNode *check_point; // Check point of the test if there's a
72 void *state; // State associated with the test.
75 // Determines whether two values are the same.
76 typedef int (*EqualityFunction)(const void *left, const void *right);
78 // Value of a symbol and the place it was declared.
79 typedef struct SymbolValue {
80 SourceLocation location;
84 /* Contains a list of values for a symbol.
85 * NOTE: Each structure referenced by symbol_values_list_head must have a
86 * SourceLocation as its' first member.
88 typedef struct SymbolMapValue {
89 const char *symbol_name;
90 ListNode symbol_values_list_head;
93 // Used by list_free() to deallocate values referenced by list nodes.
94 typedef void (*CleanupListValue)(const void *value, void *cleanup_value_data);
96 // Structure used to check the range of integer types.
97 typedef struct CheckIntegerRange {
98 CheckParameterEvent event;
103 // Structure used to check whether an integer value is in a set.
104 typedef struct CheckIntegerSet {
105 CheckParameterEvent event;
110 /* Used to check whether a parameter matches the area of memory referenced by
112 typedef struct CheckMemoryData {
113 CheckParameterEvent event;
118 static ListNode* list_initialize(ListNode * const node);
119 static ListNode* list_add(ListNode * const head, ListNode *new_node);
120 static ListNode* list_add_value(ListNode * const head, const void *value,
122 static ListNode* list_remove(
123 ListNode * const node, const CleanupListValue cleanup_value,
124 void * const cleanup_value_data);
125 static void list_remove_free(
126 ListNode * const node, const CleanupListValue cleanup_value,
127 void * const cleanup_value_data);
128 static int list_empty(const ListNode * const head);
129 static int list_find(
130 ListNode * const head, const void *value,
131 const EqualityFunction equal_func, ListNode **output);
132 static int list_first(ListNode * const head, ListNode **output);
133 static ListNode* list_free(
134 ListNode * const head, const CleanupListValue cleanup_value,
135 void * const cleanup_value_data);
137 static void add_symbol_value(
138 ListNode * const symbol_map_head, const char * const symbol_names[],
139 const size_t number_of_symbol_names, const void* value, const int count);
140 static int get_symbol_value(
141 ListNode * const symbol_map_head, const char * const symbol_names[],
142 const size_t number_of_symbol_names, void **output);
143 static void free_value(const void *value, void *cleanup_value_data);
144 static void free_symbol_map_value(
145 const void *value, void *cleanup_value_data);
146 static void remove_always_return_values(ListNode * const map_head,
147 const size_t number_of_symbol_names);
148 static int check_for_leftover_values(
149 const ListNode * const map_head, const char * const error_message,
150 const size_t number_of_symbol_names);
151 // This must be called at the beginning of a test to initialize some data
153 static void initialize_testing(const char *test_name);
154 // This must be called at the end of a test to free() allocated structures.
155 static void teardown_testing(const char *test_name);
158 // Keeps track of the calling context returned by setenv() so that the fail()
159 // method can jump out of a test.
160 static jmp_buf global_run_test_env;
161 static int global_running_test = 0;
163 // Keeps track of the calling context returned by setenv() so that
164 // mock_assert() can optionally jump back to expect_assert_failure().
165 jmp_buf global_expect_assert_env;
166 int global_expecting_assert = 0;
168 // Keeps a map of the values that functions will have to return to provide
169 // mocked interfaces.
170 static ListNode global_function_result_map_head;
171 // Location of the last mock value returned was declared.
172 static SourceLocation global_last_mock_value_location;
174 /* Keeps a map of the values that functions expect as parameters to their
175 * mocked interfaces. */
176 static ListNode global_function_parameter_map_head;
177 // Location of last parameter value checked was declared.
178 static SourceLocation global_last_parameter_location;
180 // List of all currently allocated blocks.
181 static ListNode global_allocated_blocks;
184 // Signals caught by exception_handler().
185 static const int exception_signals[] = {
193 // Default signal functions that should be restored after a test is complete.
194 typedef void (*SignalFunction)(int signal);
195 static SignalFunction default_signal_functions[
196 ARRAY_LENGTH(exception_signals)];
200 // The default exception filter.
201 static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter;
204 typedef struct ExceptionCodeInfo {
206 const char* description;
209 #define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code}
211 static const ExceptionCodeInfo exception_codes[] = {
212 EXCEPTION_CODE_INFO(EXCEPTION_ACCESS_VIOLATION),
213 EXCEPTION_CODE_INFO(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),
214 EXCEPTION_CODE_INFO(EXCEPTION_DATATYPE_MISALIGNMENT),
215 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DENORMAL_OPERAND),
216 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DIVIDE_BY_ZERO),
217 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INEXACT_RESULT),
218 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INVALID_OPERATION),
219 EXCEPTION_CODE_INFO(EXCEPTION_FLT_OVERFLOW),
220 EXCEPTION_CODE_INFO(EXCEPTION_FLT_STACK_CHECK),
221 EXCEPTION_CODE_INFO(EXCEPTION_FLT_UNDERFLOW),
222 EXCEPTION_CODE_INFO(EXCEPTION_GUARD_PAGE),
223 EXCEPTION_CODE_INFO(EXCEPTION_ILLEGAL_INSTRUCTION),
224 EXCEPTION_CODE_INFO(EXCEPTION_INT_DIVIDE_BY_ZERO),
225 EXCEPTION_CODE_INFO(EXCEPTION_INT_OVERFLOW),
226 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_DISPOSITION),
227 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_HANDLE),
228 EXCEPTION_CODE_INFO(EXCEPTION_IN_PAGE_ERROR),
229 EXCEPTION_CODE_INFO(EXCEPTION_NONCONTINUABLE_EXCEPTION),
230 EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION),
231 EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW),
236 // Exit the currently executing test.
237 static void exit_test(const int quit_application) {
238 if (global_running_test) {
239 longjmp(global_run_test_env, 1);
240 } else if (quit_application) {
246 // Initialize a SourceLocation structure.
247 static void initialize_source_location(SourceLocation * const location) {
248 assert_true(location);
249 location->file = NULL;
254 // Determine whether a source location is currently set.
255 static int source_location_is_set(const SourceLocation * const location) {
256 assert_true(location);
257 return location->file && location->line;
261 // Set a source location.
262 static void set_source_location(
263 SourceLocation * const location, const char * const file,
265 assert_true(location);
266 location->file = file;
267 location->line = line;
271 // Create function results and expected parameter lists.
272 void initialize_testing(const char *test_name) {
273 list_initialize(&global_function_result_map_head);
274 initialize_source_location(&global_last_mock_value_location);
275 list_initialize(&global_function_parameter_map_head);
276 initialize_source_location(&global_last_parameter_location);
280 void fail_if_leftover_values(const char *test_name) {
281 int error_occurred = 0;
282 remove_always_return_values(&global_function_result_map_head, 1);
283 if (check_for_leftover_values(
284 &global_function_result_map_head,
285 "%s() has remaining non-returned values.\n", 1)) {
289 remove_always_return_values(&global_function_parameter_map_head, 2);
290 if (check_for_leftover_values(
291 &global_function_parameter_map_head,
292 "%s parameter still has values that haven't been checked.\n", 2)) {
295 if (error_occurred) {
301 void teardown_testing(const char *test_name) {
302 list_free(&global_function_result_map_head, free_symbol_map_value,
304 initialize_source_location(&global_last_mock_value_location);
305 list_free(&global_function_parameter_map_head, free_symbol_map_value,
307 initialize_source_location(&global_last_parameter_location);
310 // Initialize a list node.
311 static ListNode* list_initialize(ListNode * const node) {
320 /* Adds a value at the tail of a given list.
321 * The node referencing the value is allocated from the heap. */
322 static ListNode* list_add_value(ListNode * const head, const void *value,
323 const int refcount) {
324 ListNode * const new_node = (ListNode*)malloc(sizeof(ListNode));
327 new_node->value = value;
328 new_node->refcount = refcount;
329 return list_add(head, new_node);
333 // Add new_node to the end of the list.
334 static ListNode* list_add(ListNode * const head, ListNode *new_node) {
336 assert_true(new_node);
337 new_node->next = head;
338 new_node->prev = head->prev;
339 head->prev->next = new_node;
340 head->prev = new_node;
345 // Remove a node from a list.
346 static ListNode* list_remove(
347 ListNode * const node, const CleanupListValue cleanup_value,
348 void * const cleanup_value_data) {
350 node->prev->next = node->next;
351 node->next->prev = node->prev;
353 cleanup_value(node->value, cleanup_value_data);
359 /* Remove a list node from a list and free the node. */
360 static void list_remove_free(
361 ListNode * const node, const CleanupListValue cleanup_value,
362 void * const cleanup_value_data) {
364 free(list_remove(node, cleanup_value, cleanup_value_data));
368 /* Frees memory kept by a linked list
369 * The cleanup_value function is called for every "value" field of nodes in the
370 * list, except for the head. In addition to each list value,
371 * cleanup_value_data is passed to each call to cleanup_value. The head
372 * of the list is not deallocated.
374 static ListNode* list_free(
375 ListNode * const head, const CleanupListValue cleanup_value,
376 void * const cleanup_value_data) {
378 while (!list_empty(head)) {
379 list_remove_free(head->next, cleanup_value, cleanup_value_data);
385 // Determine whether a list is empty.
386 static int list_empty(const ListNode * const head) {
388 return head->next == head;
392 /* Find a value in the list using the equal_func to compare each node with the
395 static int list_find(ListNode * const head, const void *value,
396 const EqualityFunction equal_func, ListNode **output) {
399 for (current = head->next; current != head; current = current->next) {
400 if (equal_func(current->value, value)) {
408 // Returns the first node of a list
409 static int list_first(ListNode * const head, ListNode **output) {
410 ListNode *target_node;
412 if (list_empty(head)) {
415 target_node = head->next;
416 *output = target_node;
421 // Deallocate a value referenced by a list.
422 static void free_value(const void *value, void *cleanup_value_data) {
428 // Releases memory associated to a symbol_map_value.
429 static void free_symbol_map_value(const void *value,
430 void *cleanup_value_data) {
431 SymbolMapValue * const map_value = (SymbolMapValue*)value;
432 const unsigned int children = (unsigned int)cleanup_value_data;
434 list_free(&map_value->symbol_values_list_head,
435 children ? free_symbol_map_value : free_value,
436 (void*)(children - 1));
441 /* Determine whether a symbol name referenced by a symbol_map_value
442 * matches the specified function name. */
443 static int symbol_names_match(const void *map_value, const void *symbol) {
444 return !strcmp(((SymbolMapValue*)map_value)->symbol_name,
445 (const char*)symbol);
449 /* Adds a value to the queue of values associated with the given
450 * hierarchy of symbols. It's assumed value is allocated from the heap.
452 static void add_symbol_value(ListNode * const symbol_map_head,
453 const char * const symbol_names[],
454 const size_t number_of_symbol_names,
455 const void* value, const int refcount) {
456 const char* symbol_name;
457 ListNode *target_node;
458 SymbolMapValue *target_map_value;
459 assert_true(symbol_map_head);
460 assert_true(symbol_names);
461 assert_true(number_of_symbol_names);
462 symbol_name = symbol_names[0];
464 if (!list_find(symbol_map_head, symbol_name, symbol_names_match,
466 SymbolMapValue * const new_symbol_map_value =
467 malloc(sizeof(*new_symbol_map_value));
468 new_symbol_map_value->symbol_name = symbol_name;
469 list_initialize(&new_symbol_map_value->symbol_values_list_head);
470 target_node = list_add_value(symbol_map_head, new_symbol_map_value,
474 target_map_value = (SymbolMapValue*)target_node->value;
475 if (number_of_symbol_names == 1) {
476 list_add_value(&target_map_value->symbol_values_list_head,
479 add_symbol_value(&target_map_value->symbol_values_list_head,
480 &symbol_names[1], number_of_symbol_names - 1, value,
486 /* Gets the next value associated with the given hierarchy of symbols.
487 * The value is returned as an output parameter with the function returning the
488 * node's old refcount value if a value is found, 0 otherwise.
489 * This means that a return value of 1 indicates the node was just removed from
492 static int get_symbol_value(
493 ListNode * const head, const char * const symbol_names[],
494 const size_t number_of_symbol_names, void **output) {
495 const char* symbol_name;
496 ListNode *target_node;
498 assert_true(symbol_names);
499 assert_true(number_of_symbol_names);
501 symbol_name = symbol_names[0];
503 if (list_find(head, symbol_name, symbol_names_match, &target_node)) {
504 SymbolMapValue *map_value;
505 ListNode *child_list;
506 int return_value = 0;
507 assert_true(target_node);
508 assert_true(target_node->value);
510 map_value = (SymbolMapValue*)target_node->value;
511 child_list = &map_value->symbol_values_list_head;
513 if (number_of_symbol_names == 1) {
514 ListNode *value_node = NULL;
515 return_value = list_first(child_list, &value_node);
516 assert_true(return_value);
517 *output = (void*) value_node->value;
518 return_value = value_node->refcount;
519 if (--value_node->refcount == 0) {
520 list_remove_free(value_node, NULL, NULL);
523 return_value = get_symbol_value(
524 child_list, &symbol_names[1], number_of_symbol_names - 1,
527 if (list_empty(child_list)) {
528 list_remove_free(target_node, free_symbol_map_value, (void*)0);
532 print_error("No entries for symbol %s.\n", symbol_name);
538 /* Traverse down a tree of symbol values and remove the first symbol value
539 * in each branch that has a refcount < -1 (i.e should always be returned
540 * and has been returned at least once).
542 static void remove_always_return_values(ListNode * const map_head,
543 const size_t number_of_symbol_names) {
545 assert_true(map_head);
546 assert_true(number_of_symbol_names);
547 current = map_head->next;
548 while (current != map_head) {
549 SymbolMapValue * const value = (SymbolMapValue*)current->value;
550 ListNode * const next = current->next;
551 ListNode *child_list;
553 child_list = &value->symbol_values_list_head;
555 if (!list_empty(child_list)) {
556 if (number_of_symbol_names == 1) {
557 ListNode * const child_node = child_list->next;
558 // If this item has been returned more than once, free it.
559 if (child_node->refcount < -1) {
560 list_remove_free(child_node, free_value, NULL);
563 remove_always_return_values(child_list,
564 number_of_symbol_names - 1);
568 if (list_empty(child_list)) {
569 list_remove_free(current, free_value, NULL);
575 /* Checks if there are any leftover values set up by the test that were never
576 * retrieved through execution, and fail the test if that is the case.
578 static int check_for_leftover_values(
579 const ListNode * const map_head, const char * const error_message,
580 const size_t number_of_symbol_names) {
581 const ListNode *current;
582 int symbols_with_leftover_values = 0;
583 assert_true(map_head);
584 assert_true(number_of_symbol_names);
586 for (current = map_head->next; current != map_head;
587 current = current->next) {
588 const SymbolMapValue * const value =
589 (SymbolMapValue*)current->value;
590 const ListNode *child_list;
592 child_list = &value->symbol_values_list_head;
594 if (!list_empty(child_list)) {
595 if (number_of_symbol_names == 1) {
596 const ListNode *child_node;
597 print_error(error_message, value->symbol_name);
598 print_error(" Remaining item(s) declared at...\n");
600 for (child_node = child_list->next; child_node != child_list;
601 child_node = child_node->next) {
602 const SourceLocation * const location = child_node->value;
603 print_error(" " SOURCE_LOCATION_FORMAT "\n",
604 location->file, location->line);
607 print_error("%s.", value->symbol_name);
608 check_for_leftover_values(child_list, error_message,
609 number_of_symbol_names - 1);
611 symbols_with_leftover_values ++;
614 return symbols_with_leftover_values;
618 // Get the next return value for the specified mock function.
619 void* _mock(const char * const function, const char* const file,
622 const int rc = get_symbol_value(&global_function_result_map_head,
623 &function, 1, &result);
625 SymbolValue * const symbol = result;
626 void * const value = (void*)symbol->value;
627 global_last_mock_value_location = symbol->location;
633 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
634 "to mock function %s\n", file, line, function);
635 if (source_location_is_set(&global_last_mock_value_location)) {
636 print_error("Previously returned mock value was declared at "
637 SOURCE_LOCATION_FORMAT "\n",
638 global_last_mock_value_location.file,
639 global_last_mock_value_location.line);
641 print_error("There were no previously returned mock values for "
650 // Add a return value for the specified mock function name.
651 void _will_return(const char * const function_name, const char * const file,
652 const int line, const void* const value, const int count) {
653 SymbolValue * const return_value = malloc(sizeof(*return_value));
654 assert_true(count > 0);
655 return_value->value = value;
656 set_source_location(&return_value->location, file, line);
657 add_symbol_value(&global_function_result_map_head, &function_name, 1,
658 return_value, count);
662 /* Add a custom parameter checking function. If the event parameter is NULL
663 * the event structure is allocated internally by this function. If event
664 * parameter is provided it must be allocated on the heap and doesn't need to
665 * be deallocated by the caller.
668 const char* const function, const char* const parameter,
669 const char* const file, const int line,
670 const CheckParameterValue check_function, void * const check_data,
671 CheckParameterEvent * const event, const int count) {
672 CheckParameterEvent * const check =
673 event ? event : malloc(sizeof(*check));
674 const char* symbols[] = {function, parameter};
675 check->parameter_name = parameter;
676 check->check_value = check_function;
677 check->check_value_data = check_data;
678 set_source_location(&check->location, file, line);
679 add_symbol_value(&global_function_parameter_map_head, symbols, 2, check,
684 /* Returns 1 if the specified values are equal. If the values are not equal
685 * an error is displayed and 0 is returned. */
686 static int values_equal_display_error(const void* const left,
687 const void* const right) {
688 const int equal = left == right;
690 print_error("0x%x != 0x%x\n", left, right);
695 /* Returns 1 if the specified values are not equal. If the values are equal
696 * an error is displayed and 0 is returned. */
697 static int values_not_equal_display_error(const void* const left,
698 const void* const right) {
699 const int not_equal = left != right;
701 print_error("0x%x == 0x%x\n", left, right);
707 /* Determine whether value is contained within check_integer_set.
708 * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is
709 * returned and an error is displayed. If invert is 1 and the value is not
710 * in the set 1 is returned, otherwise 0 is returned and an error is
712 static int value_in_set_display_error(
713 const void *value, const CheckIntegerSet * const check_integer_set,
715 int succeeded = invert;
716 assert_true(check_integer_set);
718 const void ** const set = check_integer_set->set;
719 const size_t size_of_set = check_integer_set->size_of_set;
721 for (i = 0; i < size_of_set; i++) {
722 if (set[i] == value) {
732 print_error("%d is %sin the set (", value, invert ? "" : "not ");
733 for (i = 0; i < size_of_set; i++) {
734 print_error("%d, ", set[i]);
742 /* Determine whether a value is within the specified range. If the value is
743 * within the specified range 1 is returned. If the value isn't within the
744 * specified range an error is displayed and 0 is returned. */
745 static int integer_in_range_display_error(
746 const int value, const int range_min, const int range_max) {
747 if (value >= range_min && value <= range_max) {
750 print_error("%d is not within the range %d-%d\n", value, range_min,
756 /* Determine whether a value is within the specified range. If the value
757 * is not within the range 1 is returned. If the value is within the
758 * specified range an error is displayed and zero is returned. */
759 static int integer_not_in_range_display_error(
760 const int value, const int range_min, const int range_max) {
761 if (value < range_min || value > range_max) {
764 print_error("%d is within the range %d-%d\n", value, range_min,
770 /* Determine whether the specified strings are equal. If the strings are equal
771 * 1 is returned. If they're not equal an error is displayed and 0 is
773 static int string_equal_display_error(
774 const char * const left, const char * const right) {
775 if (strcmp(left, right) == 0) {
778 print_error("\"%s\" != \"%s\"\n", left, right);
783 /* Determine whether the specified strings are equal. If the strings are not
784 * equal 1 is returned. If they're not equal an error is displayed and 0 is
786 static int string_not_equal_display_error(
787 const char * const left, const char * const right) {
788 if (strcmp(left, right) != 0) {
791 print_error("\"%s\" == \"%s\"\n", left, right);
796 /* Determine whether the specified areas of memory are equal. If they're equal
797 * 1 is returned otherwise an error is displayed and 0 is returned. */
798 static int memory_equal_display_error(const char* a, const char* b,
802 for (i = 0; i < size; i++) {
806 print_error("difference at offset %d 0x%02x 0x%02x\n", i, l, r);
811 print_error("%d bytes of 0x%08x and 0x%08x differ\n", differences,
819 /* Determine whether the specified areas of memory are not equal. If they're
820 * not equal 1 is returned otherwise an error is displayed and 0 is
822 static int memory_not_equal_display_error(const char* a, const char* b,
826 for (i = 0; i < size; i++) {
830 print_error("equal at offset %d 0x%02x 0x%02x\n", i, l, r);
835 print_error("%d bytes of 0x%08x and 0x%08x the same\n", same,
843 // CheckParameterValue callback to check whether a value is within a set.
844 static int check_in_set(const void *value, void *check_value_data) {
845 return value_in_set_display_error(value,
846 (CheckIntegerSet*)check_value_data, 0);
850 // CheckParameterValue callback to check whether a value isn't within a set.
851 static int check_not_in_set(const void *value, void *check_value_data) {
852 return value_in_set_display_error(value,
853 (CheckIntegerSet*)check_value_data, 1);
857 /* Create the callback data for check_in_set() or check_not_in_set() and
858 * register a check event. */
859 static void expect_set(
860 const char* const function, const char* const parameter,
861 const char* const file, const int line, const void *values[],
862 const size_t number_of_values,
863 const CheckParameterValue check_function, const int count) {
864 CheckIntegerSet * const check_integer_set =
865 malloc(sizeof(*check_integer_set) +
866 (sizeof(values[0]) * number_of_values));
867 void ** const set = (void**)(check_integer_set + 1);
869 assert_true(number_of_values);
870 memcpy(set, values, number_of_values * sizeof(values[0]));
871 check_integer_set->set = (const void**)set;
872 _expect_check(function, parameter, file, line, check_function,
873 check_integer_set, &check_integer_set->event, count);
877 // Add an event to check whether a value is in a set.
879 const char* const function, const char* const parameter,
880 const char* const file, const int line, const void *values[],
881 const size_t number_of_values, const int count) {
882 expect_set(function, parameter, file, line, values, number_of_values,
883 check_in_set, count);
887 // Add an event to check whether a value isn't in a set.
888 void _expect_not_in_set(
889 const char* const function, const char* const parameter,
890 const char* const file, const int line, const void *values[],
891 const size_t number_of_values, const int count) {
892 expect_set(function, parameter, file, line, values, number_of_values,
893 check_not_in_set, count);
897 // CheckParameterValue callback to check whether a value is within a range.
898 static int check_in_range(const void *value, void *check_value_data) {
899 CheckIntegerRange * const check_integer_range = check_value_data;
900 assert_true(check_value_data);
901 return integer_in_range_display_error(
902 (int)value, check_integer_range->minimum,
903 check_integer_range->maximum);
907 // CheckParameterValue callback to check whether a value is not within a range.
908 static int check_not_in_range(const void *value, void *check_value_data) {
909 CheckIntegerRange * const check_integer_range = check_value_data;
910 assert_true(check_value_data);
911 return integer_not_in_range_display_error(
912 (int)value, check_integer_range->minimum,
913 check_integer_range->maximum);
917 /* Create the callback data for check_in_range() or check_not_in_range() and
918 * register a check event. */
919 static void expect_range(
920 const char* const function, const char* const parameter,
921 const char* const file, const int line,
922 const int minimum, const int maximum,
923 const CheckParameterValue check_function, const int count) {
924 CheckIntegerRange * const check_integer_range =
925 malloc(sizeof(*check_integer_range));
926 check_integer_range->minimum = minimum;
927 check_integer_range->maximum = maximum;
928 _expect_check(function, parameter, file, line, check_function,
929 check_integer_range, &check_integer_range->event, count);
933 // Add an event to determine whether a parameter is within a range.
934 void _expect_in_range(
935 const char* const function, const char* const parameter,
936 const char* const file, const int line,
937 const int minimum, const int maximum, const int count) {
938 expect_range(function, parameter, file, line, minimum, maximum,
939 check_in_range, count);
943 // Add an event to determine whether a parameter is not within a range.
944 void _expect_not_in_range(
945 const char* const function, const char* const parameter,
946 const char* const file, const int line,
947 const int minimum, const int maximum, const int count) {
948 expect_range(function, parameter, file, line, minimum, maximum,
949 check_not_in_range, count);
953 /* CheckParameterValue callback to check whether a value is equal to an
955 static int check_value(const void *value, void *check_value_data) {
956 return values_equal_display_error(value, check_value_data);
960 // Add an event to check a parameter equals an expected value.
962 const char* const function, const char* const parameter,
963 const char* const file, const int line, const void* const value,
965 _expect_check(function, parameter, file, line, check_value,
966 (void*)value, NULL, count);
970 /* CheckParameterValue callback to check whether a value is not equal to an
972 static int check_not_value(const void *value, void *check_value_data) {
973 return values_not_equal_display_error(value, check_value_data);
977 // Add an event to check a parameter is not equal to an expected value.
978 void _expect_not_value(
979 const char* const function, const char* const parameter,
980 const char* const file, const int line, const void* const value,
982 _expect_check(function, parameter, file, line, check_not_value,
983 (void*)value, NULL, count);
987 // CheckParameterValue callback to check whether a parameter equals a string.
988 static int check_string(const void * value, void *check_value_data) {
989 return string_equal_display_error(value, check_value_data);
993 // Add an event to check whether a parameter is equal to a string.
995 const char* const function, const char* const parameter,
996 const char* const file, const int line, const char* string,
998 _expect_check(function, parameter, file, line, check_string, (void*)string,
1003 /* CheckParameterValue callback to check whether a parameter is not equals to
1005 static int check_not_string(const void * value, void *check_value_data) {
1006 return string_not_equal_display_error(value, check_value_data);
1010 // Add an event to check whether a parameter is not equal to a string.
1011 void _expect_not_string(
1012 const char* const function, const char* const parameter,
1013 const char* const file, const int line, const char* string,
1015 _expect_check(function, parameter, file, line, check_not_string,
1016 (void*)string, NULL, count);
1019 /* CheckParameterValue callback to check whether a parameter equals an area of
1021 static int check_memory(const void* value, void *check_value_data) {
1022 CheckMemoryData * const check = (CheckMemoryData*)check_value_data;
1024 return memory_equal_display_error(value, check->memory, check->size);
1028 /* Create the callback data for check_memory() or check_not_memory() and
1029 * register a check event. */
1030 static void expect_memory_setup(
1031 const char* const function, const char* const parameter,
1032 const char* const file, const int line,
1033 const void * const memory, const size_t size,
1034 const CheckParameterValue check_function, const int count) {
1035 CheckMemoryData * const check_data = malloc(sizeof(*check_data) + size);
1036 void * const mem = (void*)(check_data + 1);
1037 assert_true(memory);
1039 memcpy(mem, memory, size);
1040 check_data->memory = mem;
1041 check_data->size = size;
1042 _expect_check(function, parameter, file, line, check_function,
1043 check_data, &check_data->event, count);
1047 // Add an event to check whether a parameter matches an area of memory.
1048 void _expect_memory(
1049 const char* const function, const char* const parameter,
1050 const char* const file, const int line, const void* const memory,
1051 const size_t size, const int count) {
1052 expect_memory_setup(function, parameter, file, line, memory, size,
1053 check_memory, count);
1057 /* CheckParameterValue callback to check whether a parameter is not equal to
1058 * an area of memory. */
1059 static int check_not_memory(const void* value, void *check_value_data) {
1060 CheckMemoryData * const check = (CheckMemoryData*)check_value_data;
1062 return memory_not_equal_display_error(value, check->memory, check->size);
1066 // Add an event to check whether a parameter doesn't match an area of memory.
1067 void _expect_not_memory(
1068 const char* const function, const char* const parameter,
1069 const char* const file, const int line, const void* const memory,
1070 const size_t size, const int count) {
1071 expect_memory_setup(function, parameter, file, line, memory, size,
1072 check_not_memory, count);
1076 // CheckParameterValue callback that always returns 1.
1077 static int check_any(const void *value, void *check_value_data) {
1082 // Add an event to allow any value for a parameter.
1084 const char* const function, const char* const parameter,
1085 const char* const file, const int line, const int count) {
1086 _expect_check(function, parameter, file, line, check_any, NULL, NULL,
1091 void _check_expected(
1092 const char * const function_name, const char * const parameter_name,
1093 const char* file, const int line, const void* value) {
1095 const char* symbols[] = {function_name, parameter_name};
1096 const int rc = get_symbol_value(&global_function_parameter_map_head,
1097 symbols, 2, &result);
1099 CheckParameterEvent * const check = (CheckParameterEvent*)result;
1100 int check_succeeded;
1101 global_last_parameter_location = check->location;
1102 check_succeeded = check->check_value(value, check->check_value_data);
1106 if (!check_succeeded) {
1107 print_error("ERROR: Check of parameter %s, function %s failed\n"
1108 "Expected parameter declared at "
1109 SOURCE_LOCATION_FORMAT "\n",
1110 parameter_name, function_name,
1111 global_last_parameter_location.file,
1112 global_last_parameter_location.line);
1116 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
1117 "to check parameter %s of function %s\n", file, line,
1118 parameter_name, function_name);
1119 if (source_location_is_set(&global_last_parameter_location)) {
1120 print_error("Previously declared parameter value was declared at "
1121 SOURCE_LOCATION_FORMAT "\n",
1122 global_last_parameter_location.file,
1123 global_last_parameter_location.line);
1125 print_error("There were no previously declared parameter values "
1126 "for this test.\n");
1133 // Replacement for assert.
1134 void mock_assert(const int result, const char* const expression,
1135 const char* const file, const int line) {
1137 if (global_expecting_assert) {
1138 longjmp(global_expect_assert_env, (int)expression);
1140 print_error("ASSERT: %s\n", expression);
1147 void _assert_true(const int result, const char * const expression,
1148 const char * const file, const int line) {
1150 print_error("%s\n", expression);
1155 void _assert_int_equal(const int a, const int b, const char * const file,
1157 if (!values_equal_display_error((void*)a, (void*)b)) {
1163 void _assert_int_not_equal(const int a, const int b, const char * const file,
1165 if (!values_not_equal_display_error((void*)a, (void*)b)) {
1171 void _assert_string_equal(const char * const a, const char * const b,
1172 const char * const file, const int line) {
1173 if (!string_equal_display_error(a, b)) {
1179 void _assert_string_not_equal(const char * const a, const char * const b,
1180 const char *file, const int line) {
1181 if (!string_not_equal_display_error(a, b)) {
1187 void _assert_memory_equal(const void * const a, const void * const b,
1188 const size_t size, const char* const file,
1190 if (!memory_equal_display_error((const char*)a, (const char*)b, size)) {
1196 void _assert_memory_not_equal(const void * const a, const void * const b,
1197 const size_t size, const char* const file,
1199 if (!memory_not_equal_display_error((const char*)a, (const char*)b,
1206 void _assert_in_range(const int value, const int minimum, const int maximum,
1207 const char* const file, const int line) {
1208 if (!integer_in_range_display_error(value, minimum, maximum)) {
1213 void _assert_not_in_range(const int value, const int minimum,
1214 const int maximum, const char* const file,
1216 if (!integer_not_in_range_display_error(value, minimum, maximum)) {
1221 void _assert_in_set(const void* const value, const void *values[],
1222 const size_t number_of_values, const char* const file,
1224 CheckIntegerSet check_integer_set;
1225 check_integer_set.set = values;
1226 check_integer_set.size_of_set = number_of_values;
1227 if (!value_in_set_display_error(value, &check_integer_set, 0)) {
1232 void _assert_not_in_set(const void* const value, const void *values[],
1233 const size_t number_of_values, const char* const file,
1235 CheckIntegerSet check_integer_set;
1236 check_integer_set.set = values;
1237 check_integer_set.size_of_set = number_of_values;
1238 if (!value_in_set_display_error(value, &check_integer_set, 1)) {
1244 // Get the list of allocated blocks.
1245 static ListNode* get_allocated_blocks_list() {
1246 // If it initialized, initialize the list of allocated blocks.
1247 if (!global_allocated_blocks.value) {
1248 list_initialize(&global_allocated_blocks);
1249 global_allocated_blocks.value = (void*)1;
1251 return &global_allocated_blocks;
1254 // Use the real malloc in this function.
1256 void* _test_malloc(const size_t size, const char* file, const int line) {
1258 MallocBlockInfo *block_info;
1259 ListNode * const block_list = get_allocated_blocks_list();
1260 const size_t allocate_size = size + (MALLOC_GUARD_SIZE * 2) +
1261 sizeof(*block_info) + MALLOC_ALIGNMENT;
1262 char* const block = (char*)malloc(allocate_size);
1265 // Calculate the returned address.
1266 ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE + sizeof(*block_info) +
1267 MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1));
1269 // Initialize the guard blocks.
1270 memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
1271 memset(ptr + size, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
1272 memset(ptr, MALLOC_ALLOC_PATTERN, size);
1274 block_info = (MallocBlockInfo*)(ptr - (MALLOC_GUARD_SIZE +
1275 sizeof(*block_info)));
1276 set_source_location(&block_info->location, file, line);
1277 block_info->allocated_size = allocate_size;
1278 block_info->size = size;
1279 block_info->block = block;
1280 block_info->node.value = block_info;
1281 list_add(block_list, &block_info->node);
1284 #define malloc test_malloc
1287 void* _test_calloc(const size_t number_of_elements, const size_t size,
1288 const char* file, const int line) {
1289 void* const ptr = _test_malloc(number_of_elements * size, file, line);
1291 memset(ptr, 0, number_of_elements * size);
1297 // Use the real free in this function.
1299 void _test_free(void* const ptr, const char* file, const int line) {
1301 char *block = (char*)ptr;
1302 MallocBlockInfo *block_info;
1303 _assert_true((int)ptr, "ptr", file, line);
1304 block_info = (MallocBlockInfo*)(block - (MALLOC_GUARD_SIZE +
1305 sizeof(*block_info)));
1306 // Check the guard blocks.
1308 char *guards[2] = {block - MALLOC_GUARD_SIZE,
1309 block + block_info->size};
1310 for (i = 0; i < ARRAY_LENGTH(guards); i++) {
1312 char * const guard = guards[i];
1313 for (j = 0; j < MALLOC_GUARD_SIZE; j++) {
1314 const char diff = guard[j] - MALLOC_GUARD_PATTERN;
1317 "Guard block of 0x%08x size=%d allocated by "
1318 SOURCE_LOCATION_FORMAT " at 0x%08x is corrupt\n",
1319 (size_t)ptr, block_info->size,
1320 block_info->location.file, block_info->location.line,
1327 list_remove(&block_info->node, NULL, NULL);
1329 block = block_info->block;
1330 memset(block, MALLOC_FREE_PATTERN, block_info->allocated_size);
1333 #define free test_free
1336 // Crudely checkpoint the current heap state.
1337 static const ListNode* check_point_allocated_blocks() {
1338 return get_allocated_blocks_list()->prev;
1342 /* Display the blocks allocated after the specified check point. This
1343 * function returns the number of blocks displayed. */
1344 static int display_allocated_blocks(const ListNode * const check_point) {
1345 const ListNode * const head = get_allocated_blocks_list();
1346 const ListNode *node;
1347 int allocated_blocks = 0;
1348 assert_true(check_point);
1349 assert_true(check_point->next);
1351 for (node = check_point->next; node != head; node = node->next) {
1352 const MallocBlockInfo * const block_info = node->value;
1353 assert_true(block_info);
1355 if (!allocated_blocks) {
1356 print_error("Blocks allocated...\n");
1358 print_error(" 0x%08x : " SOURCE_LOCATION_FORMAT "\n",
1359 block_info->block, block_info->location.file,
1360 block_info->location.line);
1361 allocated_blocks ++;
1363 return allocated_blocks;
1367 // Free all blocks allocated after the specified check point.
1368 static void free_allocated_blocks(const ListNode * const check_point) {
1369 const ListNode * const head = get_allocated_blocks_list();
1370 const ListNode *node;
1371 assert_true(check_point);
1373 node = check_point->next;
1376 while (node != head) {
1377 MallocBlockInfo * const block_info = (MallocBlockInfo*)node->value;
1379 free((char*)block_info + sizeof(*block_info) + MALLOC_GUARD_SIZE);
1384 // Fail if any any blocks are allocated after the specified check point.
1385 static void fail_if_blocks_allocated(const ListNode * const check_point,
1386 const char * const test_name) {
1387 const int allocated_blocks = display_allocated_blocks(check_point);
1388 if (allocated_blocks) {
1389 free_allocated_blocks(check_point);
1390 print_error("ERROR: %s leaked %d block(s)\n", test_name,
1397 void _fail(const char * const file, const int line) {
1398 print_error("ERROR: " SOURCE_LOCATION_FORMAT " Failure!\n", file, line);
1404 static void exception_handler(int sig) {
1405 print_error("%s\n", strsignal(sig));
1411 static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
1412 EXCEPTION_RECORD * const exception_record =
1413 exception_pointers->ExceptionRecord;
1414 const DWORD code = exception_record->ExceptionCode;
1416 for (i = 0; i < ARRAY_LENGTH(exception_codes); i++) {
1417 const ExceptionCodeInfo * const code_info = &exception_codes[i];
1418 if (code == code_info->code) {
1419 static int shown_debug_message = 0;
1421 print_error("%s occurred at 0x%08x.\n", code_info->description,
1422 exception_record->ExceptionAddress);
1423 if (!shown_debug_message) {
1426 "To debug in Visual Studio...\n"
1427 "1. Select menu item File->Open Project\n"
1428 "2. Change 'Files of type' to 'Executable Files'\n"
1429 "3. Open this executable.\n"
1430 "4. Select menu item Debug->Start\n"
1432 "Alternatively, set the environment variable \n"
1433 "UNIT_TESTING_DEBUG to 1 and rebuild this executable, \n"
1434 "then click 'Debug' in the popup dialog box.\n"
1436 shown_debug_message = 1;
1439 return EXCEPTION_EXECUTE_HANDLER;
1442 return EXCEPTION_CONTINUE_SEARCH;
1447 // Standard output and error print methods.
1448 void vprint_message(const char* const format, va_list args) {
1450 vsnprintf(buffer, sizeof(buffer), format, args);
1453 OutputDebugString(buffer);
1458 void vprint_error(const char* const format, va_list args) {
1460 vsnprintf(buffer, sizeof(buffer), format, args);
1461 fprintf(stderr, buffer);
1463 OutputDebugString(buffer);
1468 void print_message(const char* const format, ...) {
1470 va_start(args, format);
1471 vprint_message(format, args);
1476 void print_error(const char* const format, ...) {
1478 va_start(args, format);
1479 vprint_error(format, args);
1485 const char * const function_name, const UnitTestFunction Function,
1486 void ** const state, const UnitTestFunctionType function_type,
1487 const void* const heap_check_point) {
1488 const ListNode * const check_point = heap_check_point ?
1489 heap_check_point : check_point_allocated_blocks();
1490 void *current_state = NULL;
1492 int handle_exceptions = 1;
1494 handle_exceptions = !IsDebuggerPresent();
1496 #if UNIT_TESTING_DEBUG
1497 handle_exceptions = 0;
1498 #endif // UNIT_TESTING_DEBUG
1500 if (handle_exceptions) {
1503 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
1504 default_signal_functions[i] = signal(
1505 exception_signals[i], exception_handler);
1508 previous_exception_filter = SetUnhandledExceptionFilter(
1513 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
1514 print_message("%s: Starting test\n", function_name);
1516 initialize_testing(function_name);
1517 global_running_test = 1;
1518 if (setjmp(global_run_test_env) == 0) {
1519 Function(state ? state : ¤t_state);
1520 fail_if_leftover_values(function_name);
1522 /* If this is a setup function then ignore any allocated blocks
1523 * only ensure they're deallocated on tear down. */
1524 if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) {
1525 fail_if_blocks_allocated(check_point, function_name);
1528 global_running_test = 0;
1530 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
1531 print_message("%s: Test completed successfully.\n", function_name);
1535 global_running_test = 0;
1536 print_message("%s: Test failed.\n", function_name);
1538 teardown_testing(function_name);
1540 if (handle_exceptions) {
1543 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
1544 signal(exception_signals[i], default_signal_functions[i]);
1547 if (previous_exception_filter) {
1548 SetUnhandledExceptionFilter(previous_exception_filter);
1549 previous_exception_filter = NULL;
1558 int _run_tests(const UnitTest * const tests, const size_t number_of_tests) {
1559 // Whether to execute the next test.
1560 int run_next_test = 1;
1561 // Whether the previous test failed.
1562 int previous_test_failed = 0;
1563 // Check point of the heap state.
1564 const ListNode * const check_point = check_point_allocated_blocks();
1565 // Current test being executed.
1566 size_t current_test = 0;
1567 // Number of tests executed.
1568 size_t tests_executed = 0;
1569 // Number of failed tests.
1570 size_t total_failed = 0;
1571 // Number of setup functions.
1573 // Number of teardown functions.
1574 size_t teardowns = 0;
1575 /* A stack of test states. A state is pushed on the stack
1576 * when a test setup occurs and popped on tear down. */
1577 TestState* test_states = malloc(number_of_tests * sizeof(*test_states));
1578 size_t number_of_test_states = 0;
1579 // Names of the tests that failed.
1580 const char** failed_names = malloc(number_of_tests *
1581 sizeof(*failed_names));
1582 void **current_state = NULL;
1584 while (current_test < number_of_tests) {
1585 const ListNode *test_check_point = NULL;
1586 TestState *current_TestState;
1587 const UnitTest * const test = &tests[current_test++];
1588 if (!test->function) {
1592 switch (test->function_type) {
1593 case UNIT_TEST_FUNCTION_TYPE_TEST:
1596 case UNIT_TEST_FUNCTION_TYPE_SETUP: {
1597 // Checkpoint the heap before the setup.
1598 current_TestState = &test_states[number_of_test_states++];
1599 current_TestState->check_point = check_point_allocated_blocks();
1600 test_check_point = current_TestState->check_point;
1601 current_state = ¤t_TestState->state;
1602 *current_state = NULL;
1607 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
1608 // Check the heap based on the last setup checkpoint.
1609 assert_true(number_of_test_states);
1610 current_TestState = &test_states[--number_of_test_states];
1611 test_check_point = current_TestState->check_point;
1612 current_state = ¤t_TestState->state;
1616 print_error("Invalid unit test function type %d\n",
1617 test->function_type);
1622 if (run_next_test) {
1623 int failed = _run_test(test->name, test->function, current_state,
1624 test->function_type, test_check_point);
1626 failed_names[total_failed] = test->name;
1629 switch (test->function_type) {
1630 case UNIT_TEST_FUNCTION_TYPE_TEST:
1631 previous_test_failed = failed;
1632 total_failed += failed;
1636 case UNIT_TEST_FUNCTION_TYPE_SETUP:
1640 // Skip forward until the next test or setup function.
1643 previous_test_failed = 0;
1646 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
1647 // If this test failed.
1648 if (failed && !previous_test_failed) {
1653 assert_false("BUG: shouldn't be here!");
1661 print_error("%d out of %d tests failed!\n", total_failed,
1663 for (i = 0; i < total_failed; i++) {
1664 print_error(" %s\n", failed_names[i]);
1667 print_message("All %d tests passed\n", tests_executed);
1670 if (number_of_test_states) {
1671 print_error("Mismatched number of setup %d and teardown %d "
1672 "functions\n", setups, teardowns);
1677 free((void*)failed_names);
1679 fail_if_blocks_allocated(check_point, "run_tests");
1680 return (int)total_failed;