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