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 : ¤t_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 = ¤t_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 = ¤t_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