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.
37 #define vsnprintf _vsnprintf
40 /* Backwards compatibility with headers shipped with Visual Studio 2005 and
43 WINBASEAPI BOOL WINAPI IsDebuggerPresent(VOID);
46 // Size of guard bytes around dynamically allocated blocks.
47 #define MALLOC_GUARD_SIZE 16
48 // Pattern used to initialize guard blocks.
49 #define MALLOC_GUARD_PATTERN 0xEF
50 // Pattern used to initialize memory allocated with test_malloc().
51 #define MALLOC_ALLOC_PATTERN 0xBA
52 #define MALLOC_FREE_PATTERN 0xCD
53 // Alignment of allocated blocks. NOTE: This must be base2.
54 #define MALLOC_ALIGNMENT sizeof(size_t)
56 // Printf formatting for source code locations.
57 #define SOURCE_LOCATION_FORMAT "%s:%d"
59 // Calculates the number of elements in an array.
60 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
62 // Doubly linked list node.
63 typedef struct ListNode {
66 struct ListNode *next;
67 struct ListNode *prev;
70 // Debug information for malloc().
71 typedef struct MallocBlockInfo {
72 void* block; // Address of the block returned by malloc().
73 size_t allocated_size; // Total size of the allocated block.
74 size_t size; // Request block size.
75 SourceLocation location; // Where the block was allocated.
76 ListNode node; // Node within list of all allocated blocks.
79 // State of each test.
80 typedef struct TestState {
81 const ListNode *check_point; // Check point of the test if there's a
83 void *state; // State associated with the test.
86 // Determines whether two values are the same.
87 typedef int (*EqualityFunction)(const void *left, const void *right);
89 // Value of a symbol and the place it was declared.
90 typedef struct SymbolValue {
91 SourceLocation location;
95 /* Contains a list of values for a symbol.
96 * NOTE: Each structure referenced by symbol_values_list_head must have a
97 * SourceLocation as its' first member.
99 typedef struct SymbolMapValue {
100 const char *symbol_name;
101 ListNode symbol_values_list_head;
104 // Used by list_free() to deallocate values referenced by list nodes.
105 typedef void (*CleanupListValue)(const void *value, void *cleanup_value_data);
107 // Structure used to check the range of integer types.
108 typedef struct CheckIntegerRange {
109 CheckParameterEvent event;
114 // Structure used to check whether an integer value is in a set.
115 typedef struct CheckIntegerSet {
116 CheckParameterEvent event;
121 /* Used to check whether a parameter matches the area of memory referenced by
123 typedef struct CheckMemoryData {
124 CheckParameterEvent event;
129 static ListNode* list_initialize(ListNode * const node);
130 static ListNode* list_add(ListNode * const head, ListNode *new_node);
131 static ListNode* list_add_value(ListNode * const head, const void *value,
133 static ListNode* list_remove(
134 ListNode * const node, const CleanupListValue cleanup_value,
135 void * const cleanup_value_data);
136 static void list_remove_free(
137 ListNode * const node, const CleanupListValue cleanup_value,
138 void * const cleanup_value_data);
139 static int list_empty(const ListNode * const head);
140 static int list_find(
141 ListNode * const head, const void *value,
142 const EqualityFunction equal_func, ListNode **output);
143 static int list_first(ListNode * const head, ListNode **output);
144 static ListNode* list_free(
145 ListNode * const head, const CleanupListValue cleanup_value,
146 void * const cleanup_value_data);
148 static void add_symbol_value(
149 ListNode * const symbol_map_head, const char * const symbol_names[],
150 const size_t number_of_symbol_names, const void* value, const int count);
151 static int get_symbol_value(
152 ListNode * const symbol_map_head, const char * const symbol_names[],
153 const size_t number_of_symbol_names, void **output);
154 static void free_value(const void *value, void *cleanup_value_data);
155 static void free_symbol_map_value(
156 const void *value, void *cleanup_value_data);
157 static void remove_always_return_values(ListNode * const map_head,
158 const size_t number_of_symbol_names);
159 static int check_for_leftover_values(
160 const ListNode * const map_head, const char * const error_message,
161 const size_t number_of_symbol_names);
162 // This must be called at the beginning of a test to initialize some data
164 static void initialize_testing(const char *test_name);
165 // This must be called at the end of a test to free() allocated structures.
166 static void teardown_testing(const char *test_name);
169 // Keeps track of the calling context returned by setenv() so that the fail()
170 // method can jump out of a test.
171 static jmp_buf global_run_test_env;
172 static int global_running_test = 0;
174 // Keeps track of the calling context returned by setenv() so that
175 // mock_assert() can optionally jump back to expect_assert_failure().
176 jmp_buf global_expect_assert_env;
177 int global_expecting_assert = 0;
179 // Keeps a map of the values that functions will have to return to provide
180 // mocked interfaces.
181 static ListNode global_function_result_map_head;
182 // Location of the last mock value returned was declared.
183 static SourceLocation global_last_mock_value_location;
185 /* Keeps a map of the values that functions expect as parameters to their
186 * mocked interfaces. */
187 static ListNode global_function_parameter_map_head;
188 // Location of last parameter value checked was declared.
189 static SourceLocation global_last_parameter_location;
191 // List of all currently allocated blocks.
192 static ListNode global_allocated_blocks;
195 // Signals caught by exception_handler().
196 static const int exception_signals[] = {
204 // Default signal functions that should be restored after a test is complete.
205 typedef void (*SignalFunction)(int signal);
206 static SignalFunction default_signal_functions[
207 ARRAY_LENGTH(exception_signals)];
211 // The default exception filter.
212 static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter;
215 typedef struct ExceptionCodeInfo {
217 const char* description;
220 #define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code}
222 static const ExceptionCodeInfo exception_codes[] = {
223 EXCEPTION_CODE_INFO(EXCEPTION_ACCESS_VIOLATION),
224 EXCEPTION_CODE_INFO(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),
225 EXCEPTION_CODE_INFO(EXCEPTION_DATATYPE_MISALIGNMENT),
226 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DENORMAL_OPERAND),
227 EXCEPTION_CODE_INFO(EXCEPTION_FLT_DIVIDE_BY_ZERO),
228 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INEXACT_RESULT),
229 EXCEPTION_CODE_INFO(EXCEPTION_FLT_INVALID_OPERATION),
230 EXCEPTION_CODE_INFO(EXCEPTION_FLT_OVERFLOW),
231 EXCEPTION_CODE_INFO(EXCEPTION_FLT_STACK_CHECK),
232 EXCEPTION_CODE_INFO(EXCEPTION_FLT_UNDERFLOW),
233 EXCEPTION_CODE_INFO(EXCEPTION_GUARD_PAGE),
234 EXCEPTION_CODE_INFO(EXCEPTION_ILLEGAL_INSTRUCTION),
235 EXCEPTION_CODE_INFO(EXCEPTION_INT_DIVIDE_BY_ZERO),
236 EXCEPTION_CODE_INFO(EXCEPTION_INT_OVERFLOW),
237 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_DISPOSITION),
238 EXCEPTION_CODE_INFO(EXCEPTION_INVALID_HANDLE),
239 EXCEPTION_CODE_INFO(EXCEPTION_IN_PAGE_ERROR),
240 EXCEPTION_CODE_INFO(EXCEPTION_NONCONTINUABLE_EXCEPTION),
241 EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION),
242 EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW),
247 // Exit the currently executing test.
248 static void exit_test(const int quit_application) {
249 if (global_running_test) {
250 longjmp(global_run_test_env, 1);
251 } else if (quit_application) {
257 // Initialize a SourceLocation structure.
258 static void initialize_source_location(SourceLocation * const location) {
259 assert_true(location);
260 location->file = NULL;
265 // Determine whether a source location is currently set.
266 static int source_location_is_set(const SourceLocation * const location) {
267 assert_true(location);
268 return location->file && location->line;
272 // Set a source location.
273 static void set_source_location(
274 SourceLocation * const location, const char * const file,
276 assert_true(location);
277 location->file = file;
278 location->line = line;
282 // Create function results and expected parameter lists.
283 void initialize_testing(const char *test_name) {
284 list_initialize(&global_function_result_map_head);
285 initialize_source_location(&global_last_mock_value_location);
286 list_initialize(&global_function_parameter_map_head);
287 initialize_source_location(&global_last_parameter_location);
291 void fail_if_leftover_values(const char *test_name) {
292 int error_occurred = 0;
293 remove_always_return_values(&global_function_result_map_head, 1);
294 if (check_for_leftover_values(
295 &global_function_result_map_head,
296 "%s() has remaining non-returned values.\n", 1)) {
300 remove_always_return_values(&global_function_parameter_map_head, 2);
301 if (check_for_leftover_values(
302 &global_function_parameter_map_head,
303 "%s parameter still has values that haven't been checked.\n", 2)) {
306 if (error_occurred) {
312 void teardown_testing(const char *test_name) {
313 list_free(&global_function_result_map_head, free_symbol_map_value,
315 initialize_source_location(&global_last_mock_value_location);
316 list_free(&global_function_parameter_map_head, free_symbol_map_value,
318 initialize_source_location(&global_last_parameter_location);
321 // Initialize a list node.
322 static ListNode* list_initialize(ListNode * const node) {
331 /* Adds a value at the tail of a given list.
332 * The node referencing the value is allocated from the heap. */
333 static ListNode* list_add_value(ListNode * const head, const void *value,
334 const int refcount) {
335 ListNode * const new_node = (ListNode*)malloc(sizeof(ListNode));
338 new_node->value = value;
339 new_node->refcount = refcount;
340 return list_add(head, new_node);
344 // Add new_node to the end of the list.
345 static ListNode* list_add(ListNode * const head, ListNode *new_node) {
347 assert_true(new_node);
348 new_node->next = head;
349 new_node->prev = head->prev;
350 head->prev->next = new_node;
351 head->prev = new_node;
356 // Remove a node from a list.
357 static ListNode* list_remove(
358 ListNode * const node, const CleanupListValue cleanup_value,
359 void * const cleanup_value_data) {
361 node->prev->next = node->next;
362 node->next->prev = node->prev;
364 cleanup_value(node->value, cleanup_value_data);
370 /* Remove a list node from a list and free the node. */
371 static void list_remove_free(
372 ListNode * const node, const CleanupListValue cleanup_value,
373 void * const cleanup_value_data) {
375 free(list_remove(node, cleanup_value, cleanup_value_data));
379 /* Frees memory kept by a linked list
380 * The cleanup_value function is called for every "value" field of nodes in the
381 * list, except for the head. In addition to each list value,
382 * cleanup_value_data is passed to each call to cleanup_value. The head
383 * of the list is not deallocated.
385 static ListNode* list_free(
386 ListNode * const head, const CleanupListValue cleanup_value,
387 void * const cleanup_value_data) {
389 while (!list_empty(head)) {
390 list_remove_free(head->next, cleanup_value, cleanup_value_data);
396 // Determine whether a list is empty.
397 static int list_empty(const ListNode * const head) {
399 return head->next == head;
403 /* Find a value in the list using the equal_func to compare each node with the
406 static int list_find(ListNode * const head, const void *value,
407 const EqualityFunction equal_func, ListNode **output) {
410 for (current = head->next; current != head; current = current->next) {
411 if (equal_func(current->value, value)) {
419 // Returns the first node of a list
420 static int list_first(ListNode * const head, ListNode **output) {
421 ListNode *target_node;
423 if (list_empty(head)) {
426 target_node = head->next;
427 *output = target_node;
432 // Deallocate a value referenced by a list.
433 static void free_value(const void *value, void *cleanup_value_data) {
439 // Releases memory associated to a symbol_map_value.
440 static void free_symbol_map_value(const void *value,
441 void *cleanup_value_data) {
442 SymbolMapValue * const map_value = (SymbolMapValue*)value;
443 const unsigned int children = (unsigned int)cleanup_value_data;
445 list_free(&map_value->symbol_values_list_head,
446 children ? free_symbol_map_value : free_value,
447 (void*)(children - 1));
452 /* Determine whether a symbol name referenced by a symbol_map_value
453 * matches the specified function name. */
454 static int symbol_names_match(const void *map_value, const void *symbol) {
455 return !strcmp(((SymbolMapValue*)map_value)->symbol_name,
456 (const char*)symbol);
460 /* Adds a value to the queue of values associated with the given
461 * hierarchy of symbols. It's assumed value is allocated from the heap.
463 static void add_symbol_value(ListNode * const symbol_map_head,
464 const char * const symbol_names[],
465 const size_t number_of_symbol_names,
466 const void* value, const int refcount) {
467 const char* symbol_name;
468 ListNode *target_node;
469 SymbolMapValue *target_map_value;
470 assert_true(symbol_map_head);
471 assert_true(symbol_names);
472 assert_true(number_of_symbol_names);
473 symbol_name = symbol_names[0];
475 if (!list_find(symbol_map_head, symbol_name, symbol_names_match,
477 SymbolMapValue * const new_symbol_map_value =
478 malloc(sizeof(*new_symbol_map_value));
479 new_symbol_map_value->symbol_name = symbol_name;
480 list_initialize(&new_symbol_map_value->symbol_values_list_head);
481 target_node = list_add_value(symbol_map_head, new_symbol_map_value,
485 target_map_value = (SymbolMapValue*)target_node->value;
486 if (number_of_symbol_names == 1) {
487 list_add_value(&target_map_value->symbol_values_list_head,
490 add_symbol_value(&target_map_value->symbol_values_list_head,
491 &symbol_names[1], number_of_symbol_names - 1, value,
497 /* Gets the next value associated with the given hierarchy of symbols.
498 * The value is returned as an output parameter with the function returning the
499 * node's old refcount value if a value is found, 0 otherwise.
500 * This means that a return value of 1 indicates the node was just removed from
503 static int get_symbol_value(
504 ListNode * const head, const char * const symbol_names[],
505 const size_t number_of_symbol_names, void **output) {
506 const char* symbol_name;
507 ListNode *target_node;
509 assert_true(symbol_names);
510 assert_true(number_of_symbol_names);
512 symbol_name = symbol_names[0];
514 if (list_find(head, symbol_name, symbol_names_match, &target_node)) {
515 SymbolMapValue *map_value;
516 ListNode *child_list;
517 int return_value = 0;
518 assert_true(target_node);
519 assert_true(target_node->value);
521 map_value = (SymbolMapValue*)target_node->value;
522 child_list = &map_value->symbol_values_list_head;
524 if (number_of_symbol_names == 1) {
525 ListNode *value_node = NULL;
526 return_value = list_first(child_list, &value_node);
527 assert_true(return_value);
528 *output = (void*) value_node->value;
529 return_value = value_node->refcount;
530 if (--value_node->refcount == 0) {
531 list_remove_free(value_node, NULL, NULL);
534 return_value = get_symbol_value(
535 child_list, &symbol_names[1], number_of_symbol_names - 1,
538 if (list_empty(child_list)) {
539 list_remove_free(target_node, free_symbol_map_value, (void*)0);
543 print_error("No entries for symbol %s.\n", symbol_name);
549 /* Traverse down a tree of symbol values and remove the first symbol value
550 * in each branch that has a refcount < -1 (i.e should always be returned
551 * and has been returned at least once).
553 static void remove_always_return_values(ListNode * const map_head,
554 const size_t number_of_symbol_names) {
556 assert_true(map_head);
557 assert_true(number_of_symbol_names);
558 current = map_head->next;
559 while (current != map_head) {
560 SymbolMapValue * const value = (SymbolMapValue*)current->value;
561 ListNode * const next = current->next;
562 ListNode *child_list;
564 child_list = &value->symbol_values_list_head;
566 if (!list_empty(child_list)) {
567 if (number_of_symbol_names == 1) {
568 ListNode * const child_node = child_list->next;
569 // If this item has been returned more than once, free it.
570 if (child_node->refcount < -1) {
571 list_remove_free(child_node, free_value, NULL);
574 remove_always_return_values(child_list,
575 number_of_symbol_names - 1);
579 if (list_empty(child_list)) {
580 list_remove_free(current, free_value, NULL);
586 /* Checks if there are any leftover values set up by the test that were never
587 * retrieved through execution, and fail the test if that is the case.
589 static int check_for_leftover_values(
590 const ListNode * const map_head, const char * const error_message,
591 const size_t number_of_symbol_names) {
592 const ListNode *current;
593 int symbols_with_leftover_values = 0;
594 assert_true(map_head);
595 assert_true(number_of_symbol_names);
597 for (current = map_head->next; current != map_head;
598 current = current->next) {
599 const SymbolMapValue * const value =
600 (SymbolMapValue*)current->value;
601 const ListNode *child_list;
603 child_list = &value->symbol_values_list_head;
605 if (!list_empty(child_list)) {
606 if (number_of_symbol_names == 1) {
607 const ListNode *child_node;
608 print_error(error_message, value->symbol_name);
609 print_error(" Remaining item(s) declared at...\n");
611 for (child_node = child_list->next; child_node != child_list;
612 child_node = child_node->next) {
613 const SourceLocation * const location = child_node->value;
614 print_error(" " SOURCE_LOCATION_FORMAT "\n",
615 location->file, location->line);
618 print_error("%s.", value->symbol_name);
619 check_for_leftover_values(child_list, error_message,
620 number_of_symbol_names - 1);
622 symbols_with_leftover_values ++;
625 return symbols_with_leftover_values;
629 // Get the next return value for the specified mock function.
630 void* _mock(const char * const function, const char* const file,
633 const int rc = get_symbol_value(&global_function_result_map_head,
634 &function, 1, &result);
636 SymbolValue * const symbol = result;
637 void * const value = (void*)symbol->value;
638 global_last_mock_value_location = symbol->location;
644 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
645 "to mock function %s\n", file, line, function);
646 if (source_location_is_set(&global_last_mock_value_location)) {
647 print_error("Previously returned mock value was declared at "
648 SOURCE_LOCATION_FORMAT "\n",
649 global_last_mock_value_location.file,
650 global_last_mock_value_location.line);
652 print_error("There were no previously returned mock values for "
661 // Add a return value for the specified mock function name.
662 void _will_return(const char * const function_name, const char * const file,
663 const int line, const void* const value, const int count) {
664 SymbolValue * const return_value = malloc(sizeof(*return_value));
665 assert_true(count > 0 || count == -1);
666 return_value->value = value;
667 set_source_location(&return_value->location, file, line);
668 add_symbol_value(&global_function_result_map_head, &function_name, 1,
669 return_value, count);
673 /* Add a custom parameter checking function. If the event parameter is NULL
674 * the event structure is allocated internally by this function. If event
675 * parameter is provided it must be allocated on the heap and doesn't need to
676 * be deallocated by the caller.
679 const char* const function, const char* const parameter,
680 const char* const file, const int line,
681 const CheckParameterValue check_function, void * const check_data,
682 CheckParameterEvent * const event, const int count) {
683 CheckParameterEvent * const check =
684 event ? event : malloc(sizeof(*check));
685 const char* symbols[] = {function, parameter};
686 check->parameter_name = parameter;
687 check->check_value = check_function;
688 check->check_value_data = check_data;
689 set_source_location(&check->location, file, line);
690 add_symbol_value(&global_function_parameter_map_head, symbols, 2, check,
695 /* Returns 1 if the specified values are equal. If the values are not equal
696 * an error is displayed and 0 is returned. */
697 static int values_equal_display_error(const void* const left,
698 const void* const right) {
699 const int equal = left == right;
701 print_error("0x%x != 0x%x\n", left, right);
706 /* Returns 1 if the specified values are not equal. If the values are equal
707 * an error is displayed and 0 is returned. */
708 static int values_not_equal_display_error(const void* const left,
709 const void* const right) {
710 const int not_equal = left != right;
712 print_error("0x%x == 0x%x\n", left, right);
718 /* Determine whether value is contained within check_integer_set.
719 * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is
720 * returned and an error is displayed. If invert is 1 and the value is not
721 * in the set 1 is returned, otherwise 0 is returned and an error is
723 static int value_in_set_display_error(
724 const void *value, const CheckIntegerSet * const check_integer_set,
726 int succeeded = invert;
727 assert_true(check_integer_set);
729 const void ** const set = check_integer_set->set;
730 const size_t size_of_set = check_integer_set->size_of_set;
732 for (i = 0; i < size_of_set; i++) {
733 if (set[i] == value) {
734 // If invert = 0 and item is found, succeeded = 1.
735 // If invert = 1 and item is found, succeeded = 0.
736 succeeded = !succeeded;
743 print_error("%d is %sin the set (", value, invert ? "" : "not ");
744 for (i = 0; i < size_of_set; i++) {
745 print_error("%d, ", set[i]);
753 /* Determine whether a value is within the specified range. If the value is
754 * within the specified range 1 is returned. If the value isn't within the
755 * specified range an error is displayed and 0 is returned. */
756 static int integer_in_range_display_error(
757 const int value, const int range_min, const int range_max) {
758 if (value >= range_min && value <= range_max) {
761 print_error("%d is not within the range %d-%d\n", value, range_min,
767 /* Determine whether a value is within the specified range. If the value
768 * is not within the range 1 is returned. If the value is within the
769 * specified range an error is displayed and zero is returned. */
770 static int integer_not_in_range_display_error(
771 const int value, const int range_min, const int range_max) {
772 if (value < range_min || value > range_max) {
775 print_error("%d is within the range %d-%d\n", value, range_min,
781 /* Determine whether the specified strings are equal. If the strings are equal
782 * 1 is returned. If they're not equal an error is displayed and 0 is
784 static int string_equal_display_error(
785 const char * const left, const char * const right) {
786 if (strcmp(left, right) == 0) {
789 print_error("\"%s\" != \"%s\"\n", left, right);
794 /* Determine whether the specified strings are equal. If the strings are not
795 * equal 1 is returned. If they're not equal an error is displayed and 0 is
797 static int string_not_equal_display_error(
798 const char * const left, const char * const right) {
799 if (strcmp(left, right) != 0) {
802 print_error("\"%s\" == \"%s\"\n", left, right);
807 /* Determine whether the specified areas of memory are equal. If they're equal
808 * 1 is returned otherwise an error is displayed and 0 is returned. */
809 static int memory_equal_display_error(const char* a, const char* b,
813 for (i = 0; i < size; i++) {
817 print_error("difference at offset %d 0x%02x 0x%02x\n", i, l, r);
822 print_error("%d bytes of 0x%08x and 0x%08x differ\n", differences,
830 /* Determine whether the specified areas of memory are not equal. If they're
831 * not equal 1 is returned otherwise an error is displayed and 0 is
833 static int memory_not_equal_display_error(const char* a, const char* b,
837 for (i = 0; i < size; i++) {
841 print_error("equal at offset %d 0x%02x 0x%02x\n", i, l, r);
846 print_error("%d bytes of 0x%08x and 0x%08x the same\n", same,
854 // CheckParameterValue callback to check whether a value is within a set.
855 static int check_in_set(const void *value, void *check_value_data) {
856 return value_in_set_display_error(value,
857 (CheckIntegerSet*)check_value_data, 0);
861 // CheckParameterValue callback to check whether a value isn't within a set.
862 static int check_not_in_set(const void *value, void *check_value_data) {
863 return value_in_set_display_error(value,
864 (CheckIntegerSet*)check_value_data, 1);
868 /* Create the callback data for check_in_set() or check_not_in_set() and
869 * register a check event. */
870 static void expect_set(
871 const char* const function, const char* const parameter,
872 const char* const file, const int line, const void *values[],
873 const size_t number_of_values,
874 const CheckParameterValue check_function, const int count) {
875 CheckIntegerSet * const check_integer_set =
876 malloc(sizeof(*check_integer_set) +
877 (sizeof(values[0]) * number_of_values));
878 void ** const set = (void**)(check_integer_set + 1);
880 assert_true(number_of_values);
881 memcpy(set, values, number_of_values * sizeof(values[0]));
882 check_integer_set->set = (const void**)set;
883 _expect_check(function, parameter, file, line, check_function,
884 check_integer_set, &check_integer_set->event, count);
888 // Add an event to check whether a value is in a set.
890 const char* const function, const char* const parameter,
891 const char* const file, const int line, const void *values[],
892 const size_t number_of_values, const int count) {
893 expect_set(function, parameter, file, line, values, number_of_values,
894 check_in_set, count);
898 // Add an event to check whether a value isn't in a set.
899 void _expect_not_in_set(
900 const char* const function, const char* const parameter,
901 const char* const file, const int line, const void *values[],
902 const size_t number_of_values, const int count) {
903 expect_set(function, parameter, file, line, values, number_of_values,
904 check_not_in_set, count);
908 // CheckParameterValue callback to check whether a value is within a range.
909 static int check_in_range(const void *value, void *check_value_data) {
910 CheckIntegerRange * const check_integer_range = check_value_data;
911 assert_true(check_value_data);
912 return integer_in_range_display_error(
913 (int)value, check_integer_range->minimum,
914 check_integer_range->maximum);
918 // CheckParameterValue callback to check whether a value is not within a range.
919 static int check_not_in_range(const void *value, void *check_value_data) {
920 CheckIntegerRange * const check_integer_range = check_value_data;
921 assert_true(check_value_data);
922 return integer_not_in_range_display_error(
923 (int)value, check_integer_range->minimum,
924 check_integer_range->maximum);
928 /* Create the callback data for check_in_range() or check_not_in_range() and
929 * register a check event. */
930 static void expect_range(
931 const char* const function, const char* const parameter,
932 const char* const file, const int line,
933 const int minimum, const int maximum,
934 const CheckParameterValue check_function, const int count) {
935 CheckIntegerRange * const check_integer_range =
936 malloc(sizeof(*check_integer_range));
937 check_integer_range->minimum = minimum;
938 check_integer_range->maximum = maximum;
939 _expect_check(function, parameter, file, line, check_function,
940 check_integer_range, &check_integer_range->event, count);
944 // Add an event to determine whether a parameter is within a range.
945 void _expect_in_range(
946 const char* const function, const char* const parameter,
947 const char* const file, const int line,
948 const int minimum, const int maximum, const int count) {
949 expect_range(function, parameter, file, line, minimum, maximum,
950 check_in_range, count);
954 // Add an event to determine whether a parameter is not within a range.
955 void _expect_not_in_range(
956 const char* const function, const char* const parameter,
957 const char* const file, const int line,
958 const int minimum, const int maximum, const int count) {
959 expect_range(function, parameter, file, line, minimum, maximum,
960 check_not_in_range, count);
964 /* CheckParameterValue callback to check whether a value is equal to an
966 static int check_value(const void *value, void *check_value_data) {
967 return values_equal_display_error(value, check_value_data);
971 // Add an event to check a parameter equals an expected value.
973 const char* const function, const char* const parameter,
974 const char* const file, const int line, const void* const value,
976 _expect_check(function, parameter, file, line, check_value,
977 (void*)value, NULL, count);
981 /* CheckParameterValue callback to check whether a value is not equal to an
983 static int check_not_value(const void *value, void *check_value_data) {
984 return values_not_equal_display_error(value, check_value_data);
988 // Add an event to check a parameter is not equal to an expected value.
989 void _expect_not_value(
990 const char* const function, const char* const parameter,
991 const char* const file, const int line, const void* const value,
993 _expect_check(function, parameter, file, line, check_not_value,
994 (void*)value, NULL, count);
998 // CheckParameterValue callback to check whether a parameter equals a string.
999 static int check_string(const void * value, void *check_value_data) {
1000 return string_equal_display_error(value, check_value_data);
1004 // Add an event to check whether a parameter is equal to a string.
1005 void _expect_string(
1006 const char* const function, const char* const parameter,
1007 const char* const file, const int line, const char* string,
1009 _expect_check(function, parameter, file, line, check_string, (void*)string,
1014 /* CheckParameterValue callback to check whether a parameter is not equals to
1016 static int check_not_string(const void * value, void *check_value_data) {
1017 return string_not_equal_display_error(value, check_value_data);
1021 // Add an event to check whether a parameter is not equal to a string.
1022 void _expect_not_string(
1023 const char* const function, const char* const parameter,
1024 const char* const file, const int line, const char* string,
1026 _expect_check(function, parameter, file, line, check_not_string,
1027 (void*)string, NULL, count);
1030 /* CheckParameterValue callback to check whether a parameter equals an area of
1032 static int check_memory(const void* value, void *check_value_data) {
1033 CheckMemoryData * const check = (CheckMemoryData*)check_value_data;
1035 return memory_equal_display_error(value, check->memory, check->size);
1039 /* Create the callback data for check_memory() or check_not_memory() and
1040 * register a check event. */
1041 static void expect_memory_setup(
1042 const char* const function, const char* const parameter,
1043 const char* const file, const int line,
1044 const void * const memory, const size_t size,
1045 const CheckParameterValue check_function, const int count) {
1046 CheckMemoryData * const check_data = malloc(sizeof(*check_data) + size);
1047 void * const mem = (void*)(check_data + 1);
1048 assert_true(memory);
1050 memcpy(mem, memory, size);
1051 check_data->memory = mem;
1052 check_data->size = size;
1053 _expect_check(function, parameter, file, line, check_function,
1054 check_data, &check_data->event, count);
1058 // Add an event to check whether a parameter matches an area of memory.
1059 void _expect_memory(
1060 const char* const function, const char* const parameter,
1061 const char* const file, const int line, const void* const memory,
1062 const size_t size, const int count) {
1063 expect_memory_setup(function, parameter, file, line, memory, size,
1064 check_memory, count);
1068 /* CheckParameterValue callback to check whether a parameter is not equal to
1069 * an area of memory. */
1070 static int check_not_memory(const void* value, void *check_value_data) {
1071 CheckMemoryData * const check = (CheckMemoryData*)check_value_data;
1073 return memory_not_equal_display_error(value, check->memory, check->size);
1077 // Add an event to check whether a parameter doesn't match an area of memory.
1078 void _expect_not_memory(
1079 const char* const function, const char* const parameter,
1080 const char* const file, const int line, const void* const memory,
1081 const size_t size, const int count) {
1082 expect_memory_setup(function, parameter, file, line, memory, size,
1083 check_not_memory, count);
1087 // CheckParameterValue callback that always returns 1.
1088 static int check_any(const void *value, void *check_value_data) {
1093 // Add an event to allow any value for a parameter.
1095 const char* const function, const char* const parameter,
1096 const char* const file, const int line, const int count) {
1097 _expect_check(function, parameter, file, line, check_any, NULL, NULL,
1102 void _check_expected(
1103 const char * const function_name, const char * const parameter_name,
1104 const char* file, const int line, const void* value) {
1106 const char* symbols[] = {function_name, parameter_name};
1107 const int rc = get_symbol_value(&global_function_parameter_map_head,
1108 symbols, 2, &result);
1110 CheckParameterEvent * const check = (CheckParameterEvent*)result;
1111 int check_succeeded;
1112 global_last_parameter_location = check->location;
1113 check_succeeded = check->check_value(value, check->check_value_data);
1117 if (!check_succeeded) {
1118 print_error("ERROR: Check of parameter %s, function %s failed\n"
1119 "Expected parameter declared at "
1120 SOURCE_LOCATION_FORMAT "\n",
1121 parameter_name, function_name,
1122 global_last_parameter_location.file,
1123 global_last_parameter_location.line);
1127 print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
1128 "to check parameter %s of function %s\n", file, line,
1129 parameter_name, function_name);
1130 if (source_location_is_set(&global_last_parameter_location)) {
1131 print_error("Previously declared parameter value was declared at "
1132 SOURCE_LOCATION_FORMAT "\n",
1133 global_last_parameter_location.file,
1134 global_last_parameter_location.line);
1136 print_error("There were no previously declared parameter values "
1137 "for this test.\n");
1144 // Replacement for assert.
1145 void mock_assert(const int result, const char* const expression,
1146 const char* const file, const int line) {
1148 if (global_expecting_assert) {
1149 longjmp(global_expect_assert_env, (int)expression);
1151 print_error("ASSERT: %s\n", expression);
1158 void _assert_true(const int result, const char * const expression,
1159 const char * const file, const int line) {
1161 print_error("%s\n", expression);
1166 void _assert_int_equal(const int a, const int b, const char * const file,
1168 if (!values_equal_display_error((void*)a, (void*)b)) {
1174 void _assert_int_not_equal(const int a, const int b, const char * const file,
1176 if (!values_not_equal_display_error((void*)a, (void*)b)) {
1182 void _assert_string_equal(const char * const a, const char * const b,
1183 const char * const file, const int line) {
1184 if (!string_equal_display_error(a, b)) {
1190 void _assert_string_not_equal(const char * const a, const char * const b,
1191 const char *file, const int line) {
1192 if (!string_not_equal_display_error(a, b)) {
1198 void _assert_memory_equal(const void * const a, const void * const b,
1199 const size_t size, const char* const file,
1201 if (!memory_equal_display_error((const char*)a, (const char*)b, size)) {
1207 void _assert_memory_not_equal(const void * const a, const void * const b,
1208 const size_t size, const char* const file,
1210 if (!memory_not_equal_display_error((const char*)a, (const char*)b,
1217 void _assert_in_range(const int value, const int minimum, const int maximum,
1218 const char* const file, const int line) {
1219 if (!integer_in_range_display_error(value, minimum, maximum)) {
1224 void _assert_not_in_range(const int value, const int minimum,
1225 const int maximum, const char* const file,
1227 if (!integer_not_in_range_display_error(value, minimum, maximum)) {
1232 void _assert_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, 0)) {
1243 void _assert_not_in_set(const void* const value, const void *values[],
1244 const size_t number_of_values, const char* const file,
1246 CheckIntegerSet check_integer_set;
1247 check_integer_set.set = values;
1248 check_integer_set.size_of_set = number_of_values;
1249 if (!value_in_set_display_error(value, &check_integer_set, 1)) {
1255 // Get the list of allocated blocks.
1256 static ListNode* get_allocated_blocks_list() {
1257 // If it initialized, initialize the list of allocated blocks.
1258 if (!global_allocated_blocks.value) {
1259 list_initialize(&global_allocated_blocks);
1260 global_allocated_blocks.value = (void*)1;
1262 return &global_allocated_blocks;
1265 // Use the real malloc in this function.
1267 void* _test_malloc(const size_t size, const char* file, const int line) {
1269 MallocBlockInfo *block_info;
1270 ListNode * const block_list = get_allocated_blocks_list();
1271 const size_t allocate_size = size + (MALLOC_GUARD_SIZE * 2) +
1272 sizeof(*block_info) + MALLOC_ALIGNMENT;
1273 char* const block = (char*)malloc(allocate_size);
1276 // Calculate the returned address.
1277 ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE + sizeof(*block_info) +
1278 MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1));
1280 // Initialize the guard blocks.
1281 memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
1282 memset(ptr + size, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
1283 memset(ptr, MALLOC_ALLOC_PATTERN, size);
1285 block_info = (MallocBlockInfo*)(ptr - (MALLOC_GUARD_SIZE +
1286 sizeof(*block_info)));
1287 set_source_location(&block_info->location, file, line);
1288 block_info->allocated_size = allocate_size;
1289 block_info->size = size;
1290 block_info->block = block;
1291 block_info->node.value = block_info;
1292 list_add(block_list, &block_info->node);
1295 #define malloc test_malloc
1298 void* _test_calloc(const size_t number_of_elements, const size_t size,
1299 const char* file, const int line) {
1300 void* const ptr = _test_malloc(number_of_elements * size, file, line);
1302 memset(ptr, 0, number_of_elements * size);
1308 // Use the real free in this function.
1310 void _test_free(void* const ptr, const char* file, const int line) {
1312 char *block = (char*)ptr;
1313 MallocBlockInfo *block_info;
1314 _assert_true((int)ptr, "ptr", file, line);
1315 block_info = (MallocBlockInfo*)(block - (MALLOC_GUARD_SIZE +
1316 sizeof(*block_info)));
1317 // Check the guard blocks.
1319 char *guards[2] = {block - MALLOC_GUARD_SIZE,
1320 block + block_info->size};
1321 for (i = 0; i < ARRAY_LENGTH(guards); i++) {
1323 char * const guard = guards[i];
1324 for (j = 0; j < MALLOC_GUARD_SIZE; j++) {
1325 const char diff = guard[j] - MALLOC_GUARD_PATTERN;
1328 "Guard block of 0x%08x size=%d allocated by "
1329 SOURCE_LOCATION_FORMAT " at 0x%08x is corrupt\n",
1330 (size_t)ptr, block_info->size,
1331 block_info->location.file, block_info->location.line,
1338 list_remove(&block_info->node, NULL, NULL);
1340 block = block_info->block;
1341 memset(block, MALLOC_FREE_PATTERN, block_info->allocated_size);
1344 #define free test_free
1347 // Crudely checkpoint the current heap state.
1348 static const ListNode* check_point_allocated_blocks() {
1349 return get_allocated_blocks_list()->prev;
1353 /* Display the blocks allocated after the specified check point. This
1354 * function returns the number of blocks displayed. */
1355 static int display_allocated_blocks(const ListNode * const check_point) {
1356 const ListNode * const head = get_allocated_blocks_list();
1357 const ListNode *node;
1358 int allocated_blocks = 0;
1359 assert_true(check_point);
1360 assert_true(check_point->next);
1362 for (node = check_point->next; node != head; node = node->next) {
1363 const MallocBlockInfo * const block_info = node->value;
1364 assert_true(block_info);
1366 if (!allocated_blocks) {
1367 print_error("Blocks allocated...\n");
1369 print_error(" 0x%08x : " SOURCE_LOCATION_FORMAT "\n",
1370 block_info->block, block_info->location.file,
1371 block_info->location.line);
1372 allocated_blocks ++;
1374 return allocated_blocks;
1378 // Free all blocks allocated after the specified check point.
1379 static void free_allocated_blocks(const ListNode * const check_point) {
1380 const ListNode * const head = get_allocated_blocks_list();
1381 const ListNode *node;
1382 assert_true(check_point);
1384 node = check_point->next;
1387 while (node != head) {
1388 MallocBlockInfo * const block_info = (MallocBlockInfo*)node->value;
1390 free((char*)block_info + sizeof(*block_info) + MALLOC_GUARD_SIZE);
1395 // Fail if any any blocks are allocated after the specified check point.
1396 static void fail_if_blocks_allocated(const ListNode * const check_point,
1397 const char * const test_name) {
1398 const int allocated_blocks = display_allocated_blocks(check_point);
1399 if (allocated_blocks) {
1400 free_allocated_blocks(check_point);
1401 print_error("ERROR: %s leaked %d block(s)\n", test_name,
1408 void _fail(const char * const file, const int line) {
1409 print_error("ERROR: " SOURCE_LOCATION_FORMAT " Failure!\n", file, line);
1415 static void exception_handler(int sig) {
1416 print_error("%s\n", strsignal(sig));
1422 static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
1423 EXCEPTION_RECORD * const exception_record =
1424 exception_pointers->ExceptionRecord;
1425 const DWORD code = exception_record->ExceptionCode;
1427 for (i = 0; i < ARRAY_LENGTH(exception_codes); i++) {
1428 const ExceptionCodeInfo * const code_info = &exception_codes[i];
1429 if (code == code_info->code) {
1430 static int shown_debug_message = 0;
1432 print_error("%s occurred at 0x%08x.\n", code_info->description,
1433 exception_record->ExceptionAddress);
1434 if (!shown_debug_message) {
1437 "To debug in Visual Studio...\n"
1438 "1. Select menu item File->Open Project\n"
1439 "2. Change 'Files of type' to 'Executable Files'\n"
1440 "3. Open this executable.\n"
1441 "4. Select menu item Debug->Start\n"
1443 "Alternatively, set the environment variable \n"
1444 "UNIT_TESTING_DEBUG to 1 and rebuild this executable, \n"
1445 "then click 'Debug' in the popup dialog box.\n"
1447 shown_debug_message = 1;
1450 return EXCEPTION_EXECUTE_HANDLER;
1453 return EXCEPTION_CONTINUE_SEARCH;
1458 // Standard output and error print methods.
1459 void vprint_message(const char* const format, va_list args) {
1461 vsnprintf(buffer, sizeof(buffer), format, args);
1464 OutputDebugString(buffer);
1469 void vprint_error(const char* const format, va_list args) {
1471 vsnprintf(buffer, sizeof(buffer), format, args);
1472 fprintf(stderr, buffer);
1474 OutputDebugString(buffer);
1479 void print_message(const char* const format, ...) {
1481 va_start(args, format);
1482 vprint_message(format, args);
1487 void print_error(const char* const format, ...) {
1489 va_start(args, format);
1490 vprint_error(format, args);
1496 const char * const function_name, const UnitTestFunction Function,
1497 void ** const state, const UnitTestFunctionType function_type,
1498 const void* const heap_check_point) {
1499 const ListNode * const check_point = heap_check_point ?
1500 heap_check_point : check_point_allocated_blocks();
1501 void *current_state = NULL;
1503 int handle_exceptions = 1;
1505 handle_exceptions = !IsDebuggerPresent();
1507 #if UNIT_TESTING_DEBUG
1508 handle_exceptions = 0;
1509 #endif // UNIT_TESTING_DEBUG
1511 if (handle_exceptions) {
1514 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
1515 default_signal_functions[i] = signal(
1516 exception_signals[i], exception_handler);
1519 previous_exception_filter = SetUnhandledExceptionFilter(
1524 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
1525 print_message("%s: Starting test\n", function_name);
1527 initialize_testing(function_name);
1528 global_running_test = 1;
1529 if (setjmp(global_run_test_env) == 0) {
1530 Function(state ? state : ¤t_state);
1531 fail_if_leftover_values(function_name);
1533 /* If this is a setup function then ignore any allocated blocks
1534 * only ensure they're deallocated on tear down. */
1535 if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) {
1536 fail_if_blocks_allocated(check_point, function_name);
1539 global_running_test = 0;
1541 if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
1542 print_message("%s: Test completed successfully.\n", function_name);
1546 global_running_test = 0;
1547 print_message("%s: Test failed.\n", function_name);
1549 teardown_testing(function_name);
1551 if (handle_exceptions) {
1554 for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
1555 signal(exception_signals[i], default_signal_functions[i]);
1558 if (previous_exception_filter) {
1559 SetUnhandledExceptionFilter(previous_exception_filter);
1560 previous_exception_filter = NULL;
1569 int _run_tests(const UnitTest * const tests, const size_t number_of_tests) {
1570 // Whether to execute the next test.
1571 int run_next_test = 1;
1572 // Whether the previous test failed.
1573 int previous_test_failed = 0;
1574 // Check point of the heap state.
1575 const ListNode * const check_point = check_point_allocated_blocks();
1576 // Current test being executed.
1577 size_t current_test = 0;
1578 // Number of tests executed.
1579 size_t tests_executed = 0;
1580 // Number of failed tests.
1581 size_t total_failed = 0;
1582 // Number of setup functions.
1584 // Number of teardown functions.
1585 size_t teardowns = 0;
1586 /* A stack of test states. A state is pushed on the stack
1587 * when a test setup occurs and popped on tear down. */
1588 TestState* test_states = malloc(number_of_tests * sizeof(*test_states));
1589 size_t number_of_test_states = 0;
1590 // Names of the tests that failed.
1591 const char** failed_names = malloc(number_of_tests *
1592 sizeof(*failed_names));
1593 void **current_state = NULL;
1595 while (current_test < number_of_tests) {
1596 const ListNode *test_check_point = NULL;
1597 TestState *current_TestState;
1598 const UnitTest * const test = &tests[current_test++];
1599 if (!test->function) {
1603 switch (test->function_type) {
1604 case UNIT_TEST_FUNCTION_TYPE_TEST:
1607 case UNIT_TEST_FUNCTION_TYPE_SETUP: {
1608 // Checkpoint the heap before the setup.
1609 current_TestState = &test_states[number_of_test_states++];
1610 current_TestState->check_point = check_point_allocated_blocks();
1611 test_check_point = current_TestState->check_point;
1612 current_state = ¤t_TestState->state;
1613 *current_state = NULL;
1618 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
1619 // Check the heap based on the last setup checkpoint.
1620 assert_true(number_of_test_states);
1621 current_TestState = &test_states[--number_of_test_states];
1622 test_check_point = current_TestState->check_point;
1623 current_state = ¤t_TestState->state;
1627 print_error("Invalid unit test function type %d\n",
1628 test->function_type);
1633 if (run_next_test) {
1634 int failed = _run_test(test->name, test->function, current_state,
1635 test->function_type, test_check_point);
1637 failed_names[total_failed] = test->name;
1640 switch (test->function_type) {
1641 case UNIT_TEST_FUNCTION_TYPE_TEST:
1642 previous_test_failed = failed;
1643 total_failed += failed;
1647 case UNIT_TEST_FUNCTION_TYPE_SETUP:
1651 // Skip forward until the next test or setup function.
1654 previous_test_failed = 0;
1657 case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
1658 // If this test failed.
1659 if (failed && !previous_test_failed) {
1664 assert_false("BUG: shouldn't be here!");
1672 print_error("%d out of %d tests failed!\n", total_failed,
1674 for (i = 0; i < total_failed; i++) {
1675 print_error(" %s\n", failed_names[i]);
1678 print_message("All %d tests passed\n", tests_executed);
1681 if (number_of_test_states) {
1682 print_error("Mismatched number of setup %d and teardown %d "
1683 "functions\n", setups, teardowns);
1688 free((void*)failed_names);
1690 fail_if_blocks_allocated(check_point, "run_tests");
1691 return (int)total_failed;