summaryrefslogtreecommitdiff
path: root/cmockery_0_1_2/src
diff options
context:
space:
mode:
authorHeather Lee Wilson <hwilson@google.com>2013-12-28 15:12:39 -0800
committerHeather Lee Wilson <hwilson@google.com>2013-12-28 15:18:58 -0800
commitbdd62c531bbdea115a3a7e71bba91c19dd319cc4 (patch)
treeca6dbdc52599a865901d0ab1121563ae1ca5f47a /cmockery_0_1_2/src
parent78931d3e5b88cec04dac31c95ca67ff6378bed76 (diff)
downloadcmockery-android-cts-5.1_r1.tar.gz
Uploading cmockery 0.1.2 to external/cmockeryandroid-wear-5.0.0_r1android-cts-5.1_r9android-cts-5.1_r8android-cts-5.1_r7android-cts-5.1_r6android-cts-5.1_r5android-cts-5.1_r4android-cts-5.1_r3android-cts-5.1_r28android-cts-5.1_r27android-cts-5.1_r26android-cts-5.1_r25android-cts-5.1_r24android-cts-5.1_r23android-cts-5.1_r22android-cts-5.1_r21android-cts-5.1_r20android-cts-5.1_r2android-cts-5.1_r19android-cts-5.1_r18android-cts-5.1_r17android-cts-5.1_r16android-cts-5.1_r15android-cts-5.1_r14android-cts-5.1_r13android-cts-5.1_r10android-cts-5.1_r1android-cts-5.0_r9android-cts-5.0_r8android-cts-5.0_r7android-cts-5.0_r6android-cts-5.0_r5android-cts-5.0_r4android-cts-5.0_r3android-5.1.1_r9android-5.1.1_r8android-5.1.1_r7android-5.1.1_r6android-5.1.1_r5android-5.1.1_r4android-5.1.1_r38android-5.1.1_r37android-5.1.1_r36android-5.1.1_r35android-5.1.1_r34android-5.1.1_r33android-5.1.1_r30android-5.1.1_r3android-5.1.1_r29android-5.1.1_r28android-5.1.1_r26android-5.1.1_r25android-5.1.1_r24android-5.1.1_r23android-5.1.1_r22android-5.1.1_r20android-5.1.1_r2android-5.1.1_r19android-5.1.1_r18android-5.1.1_r17android-5.1.1_r16android-5.1.1_r15android-5.1.1_r14android-5.1.1_r13android-5.1.1_r12android-5.1.1_r10android-5.1.1_r1android-5.1.0_r5android-5.1.0_r4android-5.1.0_r3android-5.1.0_r1android-5.0.2_r3android-5.0.2_r1android-5.0.1_r1android-5.0.0_r7android-5.0.0_r6android-5.0.0_r5.1android-5.0.0_r5android-5.0.0_r4android-5.0.0_r3android-5.0.0_r2android-5.0.0_r1lollipop-wear-releaselollipop-releaselollipop-mr1-wfc-releaselollipop-mr1-releaselollipop-mr1-fi-releaselollipop-mr1-devlollipop-mr1-cts-releaselollipop-devlollipop-cts-release
A lightweight library to simplify and generalize the process of writing unit tests for C applications. Change-Id: I460a9b6740f10593e35ae988df753a43491c6456
Diffstat (limited to 'cmockery_0_1_2/src')
-rw-r--r--cmockery_0_1_2/src/cmockery.c1680
-rw-r--r--cmockery_0_1_2/src/config.h137
-rw-r--r--cmockery_0_1_2/src/config.h.in136
-rw-r--r--cmockery_0_1_2/src/example/allocate_module.c44
-rw-r--r--cmockery_0_1_2/src/example/allocate_module_test.c47
-rw-r--r--cmockery_0_1_2/src/example/assert_macro.c37
-rw-r--r--cmockery_0_1_2/src/example/assert_macro_test.c44
-rw-r--r--cmockery_0_1_2/src/example/calculator.c266
-rw-r--r--cmockery_0_1_2/src/example/calculator_test.c425
-rw-r--r--cmockery_0_1_2/src/example/customer_database.c44
-rw-r--r--cmockery_0_1_2/src/example/customer_database_test.c69
-rw-r--r--cmockery_0_1_2/src/example/database.h37
-rw-r--r--cmockery_0_1_2/src/example/key_value.c54
-rw-r--r--cmockery_0_1_2/src/example/key_value_test.c80
-rw-r--r--cmockery_0_1_2/src/example/product_database.c22
-rw-r--r--cmockery_0_1_2/src/example/product_database_test.c66
-rw-r--r--cmockery_0_1_2/src/example/run_tests.c30
-rw-r--r--cmockery_0_1_2/src/google/cmockery.h435
18 files changed, 3653 insertions, 0 deletions
diff --git a/cmockery_0_1_2/src/cmockery.c b/cmockery_0_1_2/src/cmockery.c
new file mode 100644
index 0000000..e66304e
--- /dev/null
+++ b/cmockery_0_1_2/src/cmockery.c
@@ -0,0 +1,1680 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <setjmp.h>
+#ifndef _WIN32
+#include <signal.h>
+#endif // !_WIN32
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#endif // _WIN32
+#include <cmockery.h>
+
+#ifdef _WIN32
+#define vsnprintf _vsnprintf
+#endif // _WIN32
+
+// Size of guard bytes around dynamically allocated blocks.
+#define MALLOC_GUARD_SIZE 16
+// Pattern used to initialize guard blocks.
+#define MALLOC_GUARD_PATTERN 0xEF
+// Pattern used to initialize memory allocated with test_malloc().
+#define MALLOC_ALLOC_PATTERN 0xBA
+#define MALLOC_FREE_PATTERN 0xCD
+// Alignment of allocated blocks. NOTE: This must be base2.
+#define MALLOC_ALIGNMENT sizeof(size_t)
+
+// Printf formatting for source code locations.
+#define SOURCE_LOCATION_FORMAT "%s:%d"
+
+// Calculates the number of elements in an array.
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
+
+// Doubly linked list node.
+typedef struct ListNode {
+ const void *value;
+ int refcount;
+ struct ListNode *next;
+ struct ListNode *prev;
+} ListNode;
+
+// Debug information for malloc().
+typedef struct MallocBlockInfo {
+ void* block; // Address of the block returned by malloc().
+ size_t allocated_size; // Total size of the allocated block.
+ size_t size; // Request block size.
+ SourceLocation location; // Where the block was allocated.
+ ListNode node; // Node within list of all allocated blocks.
+} MallocBlockInfo;
+
+// State of each test.
+typedef struct TestState {
+ const ListNode *check_point; // Check point of the test if there's a
+ // setup function.
+ void *state; // State associated with the test.
+} TestState;
+
+// Determines whether two values are the same.
+typedef int (*EqualityFunction)(const void *left, const void *right);
+
+// Value of a symbol and the place it was declared.
+typedef struct SymbolValue {
+ SourceLocation location;
+ const void* value;
+} SymbolValue;
+
+/* Contains a list of values for a symbol.
+ * NOTE: Each structure referenced by symbol_values_list_head must have a
+ * SourceLocation as its' first member.
+ */
+typedef struct SymbolMapValue {
+ const char *symbol_name;
+ ListNode symbol_values_list_head;
+} SymbolMapValue;
+
+// Used by list_free() to deallocate values referenced by list nodes.
+typedef void (*CleanupListValue)(const void *value, void *cleanup_value_data);
+
+// Structure used to check the range of integer types.
+typedef struct CheckIntegerRange {
+ CheckParameterEvent event;
+ int minimum;
+ int maximum;
+} CheckIntegerRange;
+
+// Structure used to check whether an integer value is in a set.
+typedef struct CheckIntegerSet {
+ CheckParameterEvent event;
+ const void **set;
+ size_t size_of_set;
+} CheckIntegerSet;
+
+/* Used to check whether a parameter matches the area of memory referenced by
+ * this structure. */
+typedef struct CheckMemoryData {
+ CheckParameterEvent event;
+ const void *memory;
+ size_t size;
+} CheckMemoryData;
+
+static ListNode* list_initialize(ListNode * const node);
+static ListNode* list_add(ListNode * const head, ListNode *new_node);
+static ListNode* list_add_value(ListNode * const head, const void *value,
+ const int count);
+static ListNode* list_remove(
+ ListNode * const node, const CleanupListValue cleanup_value,
+ void * const cleanup_value_data);
+static void list_remove_free(
+ ListNode * const node, const CleanupListValue cleanup_value,
+ void * const cleanup_value_data);
+static int list_empty(const ListNode * const head);
+static int list_find(
+ ListNode * const head, const void *value,
+ const EqualityFunction equal_func, ListNode **output);
+static int list_first(ListNode * const head, ListNode **output);
+static ListNode* list_free(
+ ListNode * const head, const CleanupListValue cleanup_value,
+ void * const cleanup_value_data);
+
+static void 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 count);
+static int get_symbol_value(
+ ListNode * const symbol_map_head, const char * const symbol_names[],
+ const size_t number_of_symbol_names, void **output);
+static void free_value(const void *value, void *cleanup_value_data);
+static void free_symbol_map_value(
+ const void *value, void *cleanup_value_data);
+static void remove_always_return_values(ListNode * const map_head,
+ const size_t number_of_symbol_names);
+static int check_for_leftover_values(
+ const ListNode * const map_head, const char * const error_message,
+ const size_t number_of_symbol_names);
+// This must be called at the beginning of a test to initialize some data
+// structures.
+static void initialize_testing(const char *test_name);
+// This must be called at the end of a test to free() allocated structures.
+static void teardown_testing(const char *test_name);
+
+
+// Keeps track of the calling context returned by setenv() so that the fail()
+// method can jump out of a test.
+static jmp_buf global_run_test_env;
+static int global_running_test = 0;
+
+// Keeps track of the calling context returned by setenv() so that
+// mock_assert() can optionally jump back to expect_assert_failure().
+jmp_buf global_expect_assert_env;
+int global_expecting_assert = 0;
+
+// Keeps a map of the values that functions will have to return to provide
+// mocked interfaces.
+static ListNode global_function_result_map_head;
+// Location of the last mock value returned was declared.
+static SourceLocation global_last_mock_value_location;
+
+/* Keeps a map of the values that functions expect as parameters to their
+ * mocked interfaces. */
+static ListNode global_function_parameter_map_head;
+// Location of last parameter value checked was declared.
+static SourceLocation global_last_parameter_location;
+
+// List of all currently allocated blocks.
+static ListNode global_allocated_blocks;
+
+#ifndef _WIN32
+// Signals caught by exception_handler().
+static const int exception_signals[] = {
+ SIGFPE,
+ SIGILL,
+ SIGSEGV,
+ SIGBUS,
+ SIGSYS,
+};
+
+// Default signal functions that should be restored after a test is complete.
+typedef void (*SignalFunction)(int signal);
+static SignalFunction default_signal_functions[
+ ARRAY_LENGTH(exception_signals)];
+
+#else // _WIN32
+
+// The default exception filter.
+static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter;
+
+// Fatal exceptions.
+typedef struct ExceptionCodeInfo {
+ DWORD code;
+ const char* description;
+} ExceptionCodeInfo;
+
+#define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code}
+
+static const ExceptionCodeInfo exception_codes[] = {
+ EXCEPTION_CODE_INFO(EXCEPTION_ACCESS_VIOLATION),
+ EXCEPTION_CODE_INFO(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),
+ EXCEPTION_CODE_INFO(EXCEPTION_DATATYPE_MISALIGNMENT),
+ EXCEPTION_CODE_INFO(EXCEPTION_FLT_DENORMAL_OPERAND),
+ EXCEPTION_CODE_INFO(EXCEPTION_FLT_DIVIDE_BY_ZERO),
+ EXCEPTION_CODE_INFO(EXCEPTION_FLT_INEXACT_RESULT),
+ EXCEPTION_CODE_INFO(EXCEPTION_FLT_INVALID_OPERATION),
+ EXCEPTION_CODE_INFO(EXCEPTION_FLT_OVERFLOW),
+ EXCEPTION_CODE_INFO(EXCEPTION_FLT_STACK_CHECK),
+ EXCEPTION_CODE_INFO(EXCEPTION_FLT_UNDERFLOW),
+ EXCEPTION_CODE_INFO(EXCEPTION_GUARD_PAGE),
+ EXCEPTION_CODE_INFO(EXCEPTION_ILLEGAL_INSTRUCTION),
+ EXCEPTION_CODE_INFO(EXCEPTION_INT_DIVIDE_BY_ZERO),
+ EXCEPTION_CODE_INFO(EXCEPTION_INT_OVERFLOW),
+ EXCEPTION_CODE_INFO(EXCEPTION_INVALID_DISPOSITION),
+ EXCEPTION_CODE_INFO(EXCEPTION_INVALID_HANDLE),
+ EXCEPTION_CODE_INFO(EXCEPTION_IN_PAGE_ERROR),
+ EXCEPTION_CODE_INFO(EXCEPTION_NONCONTINUABLE_EXCEPTION),
+ EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION),
+ EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW),
+};
+#endif // !_WIN32
+
+
+// Exit the currently executing test.
+static void exit_test(const int quit_application) {
+ if (global_running_test) {
+ longjmp(global_run_test_env, 1);
+ } else if (quit_application) {
+ exit(-1);
+ }
+}
+
+
+// Initialize a SourceLocation structure.
+static void initialize_source_location(SourceLocation * const location) {
+ assert_true(location);
+ location->file = NULL;
+ location->line = 0;
+}
+
+
+// Determine whether a source location is currently set.
+static int source_location_is_set(const SourceLocation * const location) {
+ assert_true(location);
+ return location->file && location->line;
+}
+
+
+// Set a source location.
+static void set_source_location(
+ SourceLocation * const location, const char * const file,
+ const int line) {
+ assert_true(location);
+ location->file = file;
+ location->line = line;
+}
+
+
+// Create function results and expected parameter lists.
+void initialize_testing(const char *test_name) {
+ list_initialize(&global_function_result_map_head);
+ initialize_source_location(&global_last_mock_value_location);
+ list_initialize(&global_function_parameter_map_head);
+ initialize_source_location(&global_last_parameter_location);
+}
+
+
+void fail_if_leftover_values(const char *test_name) {
+ int error_occurred = 0;
+ remove_always_return_values(&global_function_result_map_head, 1);
+ if (check_for_leftover_values(
+ &global_function_result_map_head,
+ "%s() has remaining non-returned values.\n", 1)) {
+ error_occurred = 1;
+ }
+
+ remove_always_return_values(&global_function_parameter_map_head, 2);
+ if (check_for_leftover_values(
+ &global_function_parameter_map_head,
+ "%s parameter still has values that haven't been checked.\n", 2)) {
+ error_occurred = 1;
+ }
+ if (error_occurred) {
+ exit_test(1);
+ }
+}
+
+
+void teardown_testing(const char *test_name) {
+ list_free(&global_function_result_map_head, free_symbol_map_value,
+ (void*)0);
+ initialize_source_location(&global_last_mock_value_location);
+ list_free(&global_function_parameter_map_head, free_symbol_map_value,
+ (void*)1);
+ initialize_source_location(&global_last_parameter_location);
+}
+
+// Initialize a list node.
+static ListNode* list_initialize(ListNode * const node) {
+ node->value = NULL;
+ node->next = node;
+ node->prev = node;
+ node->refcount = 1;
+ return node;
+}
+
+
+/* Adds a value at the tail of a given list.
+ * The node referencing the value is allocated from the heap. */
+static ListNode* list_add_value(ListNode * const head, const void *value,
+ const int refcount) {
+ ListNode * const new_node = (ListNode*)malloc(sizeof(ListNode));
+ assert_true(head);
+ assert_true(value);
+ new_node->value = value;
+ new_node->refcount = refcount;
+ return list_add(head, new_node);
+}
+
+
+// Add new_node to the end of the list.
+static ListNode* list_add(ListNode * const head, ListNode *new_node) {
+ assert_true(head);
+ assert_true(new_node);
+ new_node->next = head;
+ new_node->prev = head->prev;
+ head->prev->next = new_node;
+ head->prev = new_node;
+ return new_node;
+}
+
+
+// Remove a node from a list.
+static ListNode* list_remove(
+ ListNode * const node, const CleanupListValue cleanup_value,
+ void * const cleanup_value_data) {
+ assert_true(node);
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ if (cleanup_value) {
+ cleanup_value(node->value, cleanup_value_data);
+ }
+ return node;
+}
+
+
+/* Remove a list node from a list and free the node. */
+static void list_remove_free(
+ ListNode * const node, const CleanupListValue cleanup_value,
+ void * const cleanup_value_data) {
+ assert_true(node);
+ free(list_remove(node, cleanup_value, cleanup_value_data));
+}
+
+
+/* Frees memory kept by a linked list
+ * The cleanup_value function is called for every "value" field of nodes in the
+ * list, except for the head. In addition to each list value,
+ * cleanup_value_data is passed to each call to cleanup_value. The head
+ * of the list is not deallocated.
+ */
+static ListNode* list_free(
+ ListNode * const head, const CleanupListValue cleanup_value,
+ void * const cleanup_value_data) {
+ assert_true(head);
+ while (!list_empty(head)) {
+ list_remove_free(head->next, cleanup_value, cleanup_value_data);
+ }
+ return head;
+}
+
+
+// Determine whether a list is empty.
+static int list_empty(const ListNode * const head) {
+ assert_true(head);
+ return head->next == head;
+}
+
+
+/* Find a value in the list using the equal_func to compare each node with the
+ * value.
+ */
+static int list_find(ListNode * const head, const void *value,
+ const EqualityFunction equal_func, ListNode **output) {
+ ListNode *current;
+ assert_true(head);
+ for (current = head->next; current != head; current = current->next) {
+ if (equal_func(current->value, value)) {
+ *output = current;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// Returns the first node of a list
+static int list_first(ListNode * const head, ListNode **output) {
+ ListNode *target_node;
+ assert_true(head);
+ if (list_empty(head)) {
+ return 0;
+ }
+ target_node = head->next;
+ *output = target_node;
+ return 1;
+}
+
+
+// Deallocate a value referenced by a list.
+static void free_value(const void *value, void *cleanup_value_data) {
+ assert_true(value);
+ free((void*)value);
+}
+
+
+// Releases memory associated to a symbol_map_value.
+static void free_symbol_map_value(const void *value,
+ void *cleanup_value_data) {
+ SymbolMapValue * const map_value = (SymbolMapValue*)value;
+ const unsigned int children = (unsigned int)cleanup_value_data;
+ assert_true(value);
+ list_free(&map_value->symbol_values_list_head,
+ children ? free_symbol_map_value : free_value,
+ (void*)(children - 1));
+ free(map_value);
+}
+
+
+/* Determine whether a symbol name referenced by a symbol_map_value
+ * matches the specified function name. */
+static int symbol_names_match(const void *map_value, const void *symbol) {
+ return !strcmp(((SymbolMapValue*)map_value)->symbol_name,
+ (const char*)symbol);
+}
+
+
+/* Adds a value to the queue of values associated with the given
+ * hierarchy of symbols. It's assumed value is allocated from the heap.
+ */
+static void 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) {
+ const char* symbol_name;
+ ListNode *target_node;
+ SymbolMapValue *target_map_value;
+ assert_true(symbol_map_head);
+ assert_true(symbol_names);
+ assert_true(number_of_symbol_names);
+ symbol_name = symbol_names[0];
+
+ if (!list_find(symbol_map_head, symbol_name, symbol_names_match,
+ &target_node)) {
+ SymbolMapValue * const new_symbol_map_value =
+ malloc(sizeof(*new_symbol_map_value));
+ new_symbol_map_value->symbol_name = symbol_name;
+ list_initialize(&new_symbol_map_value->symbol_values_list_head);
+ target_node = list_add_value(symbol_map_head, new_symbol_map_value,
+ 1);
+ }
+
+ target_map_value = (SymbolMapValue*)target_node->value;
+ if (number_of_symbol_names == 1) {
+ list_add_value(&target_map_value->symbol_values_list_head,
+ value, refcount);
+ } else {
+ add_symbol_value(&target_map_value->symbol_values_list_head,
+ &symbol_names[1], number_of_symbol_names - 1, value,
+ refcount);
+ }
+}
+
+
+/* Gets the next value associated with the given hierarchy of symbols.
+ * The value is returned as an output parameter with the function returning the
+ * node's old refcount value if a value is found, 0 otherwise.
+ * This means that a return value of 1 indicates the node was just removed from
+ * the list.
+ */
+static int get_symbol_value(
+ ListNode * const head, const char * const symbol_names[],
+ const size_t number_of_symbol_names, void **output) {
+ const char* symbol_name;
+ ListNode *target_node;
+ assert_true(head);
+ assert_true(symbol_names);
+ assert_true(number_of_symbol_names);
+ assert_true(output);
+ symbol_name = symbol_names[0];
+
+ if (list_find(head, symbol_name, symbol_names_match, &target_node)) {
+ SymbolMapValue *map_value;
+ ListNode *child_list;
+ int return_value = 0;
+ assert_true(target_node);
+ assert_true(target_node->value);
+
+ map_value = (SymbolMapValue*)target_node->value;
+ child_list = &map_value->symbol_values_list_head;
+
+ if (number_of_symbol_names == 1) {
+ ListNode *value_node = NULL;
+ return_value = list_first(child_list, &value_node);
+ assert_true(return_value);
+ *output = (void*) value_node->value;
+ return_value = value_node->refcount;
+ if (--value_node->refcount == 0) {
+ list_remove_free(value_node, NULL, NULL);
+ }
+ } else {
+ return_value = get_symbol_value(
+ child_list, &symbol_names[1], number_of_symbol_names - 1,
+ output);
+ }
+ if (list_empty(child_list)) {
+ list_remove_free(target_node, free_symbol_map_value, (void*)0);
+ }
+ return return_value;
+ } else {
+ print_error("No entries for symbol %s.\n", symbol_name);
+ }
+ return 0;
+}
+
+
+/* Traverse down a tree of symbol values and remove the first symbol value
+ * in each branch that has a refcount < -1 (i.e should always be returned
+ * and has been returned at least once).
+ */
+static void remove_always_return_values(ListNode * const map_head,
+ const size_t number_of_symbol_names) {
+ ListNode *current;
+ assert_true(map_head);
+ assert_true(number_of_symbol_names);
+ current = map_head->next;
+ while (current != map_head) {
+ SymbolMapValue * const value = (SymbolMapValue*)current->value;
+ ListNode * const next = current->next;
+ ListNode *child_list;
+ assert_true(value);
+ child_list = &value->symbol_values_list_head;
+
+ if (!list_empty(child_list)) {
+ if (number_of_symbol_names == 1) {
+ ListNode * const child_node = child_list->next;
+ // If this item has been returned more than once, free it.
+ if (child_node->refcount < -1) {
+ list_remove_free(child_node, free_value, NULL);
+ }
+ } else {
+ remove_always_return_values(child_list,
+ number_of_symbol_names - 1);
+ }
+ }
+
+ if (list_empty(child_list)) {
+ list_remove_free(current, free_value, NULL);
+ }
+ current = next;
+ }
+}
+
+/* Checks if there are any leftover values set up by the test that were never
+ * retrieved through execution, and fail the test if that is the case.
+ */
+static int check_for_leftover_values(
+ const ListNode * const map_head, const char * const error_message,
+ const size_t number_of_symbol_names) {
+ const ListNode *current;
+ int symbols_with_leftover_values = 0;
+ assert_true(map_head);
+ assert_true(number_of_symbol_names);
+
+ for (current = map_head->next; current != map_head;
+ current = current->next) {
+ const SymbolMapValue * const value =
+ (SymbolMapValue*)current->value;
+ const ListNode *child_list;
+ assert_true(value);
+ child_list = &value->symbol_values_list_head;
+
+ if (!list_empty(child_list)) {
+ if (number_of_symbol_names == 1) {
+ const ListNode *child_node;
+ print_error(error_message, value->symbol_name);
+ print_error(" Remaining item(s) declared at...\n");
+
+ for (child_node = child_list->next; child_node != child_list;
+ child_node = child_node->next) {
+ const SourceLocation * const location = child_node->value;
+ print_error(" " SOURCE_LOCATION_FORMAT "\n",
+ location->file, location->line);
+ }
+ } else {
+ print_error("%s.", value->symbol_name);
+ check_for_leftover_values(child_list, error_message,
+ number_of_symbol_names - 1);
+ }
+ symbols_with_leftover_values ++;
+ }
+ }
+ return symbols_with_leftover_values;
+}
+
+
+// Get the next return value for the specified mock function.
+void* _mock(const char * const function, const char* const file,
+ const int line) {
+ void *result;
+ const int rc = get_symbol_value(&global_function_result_map_head,
+ &function, 1, &result);
+ if (rc) {
+ SymbolValue * const symbol = result;
+ void * const value = (void*)symbol->value;
+ global_last_mock_value_location = symbol->location;
+ if (rc == 1) {
+ free(symbol);
+ }
+ return value;
+ } else {
+ print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
+ "to mock function %s\n", file, line, function);
+ if (source_location_is_set(&global_last_mock_value_location)) {
+ print_error("Previously returned mock value was declared at "
+ SOURCE_LOCATION_FORMAT "\n",
+ global_last_mock_value_location.file,
+ global_last_mock_value_location.line);
+ } else {
+ print_error("There were no previously returned mock values for "
+ "this test.\n");
+ }
+ exit_test(1);
+ }
+ return NULL;
+}
+
+
+// Add a return value for the specified mock function name.
+void _will_return(const char * const function_name, const char * const file,
+ const int line, const void* const value, const int count) {
+ SymbolValue * const return_value = malloc(sizeof(*return_value));
+ assert_true(count > 0);
+ return_value->value = value;
+ set_source_location(&return_value->location, file, line);
+ add_symbol_value(&global_function_result_map_head, &function_name, 1,
+ return_value, count);
+}
+
+
+/* Add a custom parameter checking function. If the event parameter is NULL
+ * the event structure is allocated internally by this function. If event
+ * parameter is provided it must be allocated on the heap and doesn't need to
+ * be deallocated by the caller.
+ */
+void _expect_check(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line,
+ const CheckParameterValue check_function, void * const check_data,
+ CheckParameterEvent * const event, const int count) {
+ CheckParameterEvent * const check =
+ event ? event : malloc(sizeof(*check));
+ const char* symbols[] = {function, parameter};
+ check->parameter_name = parameter;
+ check->check_value = check_function;
+ check->check_value_data = check_data;
+ set_source_location(&check->location, file, line);
+ add_symbol_value(&global_function_parameter_map_head, symbols, 2, check,
+ count);
+}
+
+
+/* Returns 1 if the specified values are equal. If the values are not equal
+ * an error is displayed and 0 is returned. */
+static int values_equal_display_error(const void* const left,
+ const void* const right) {
+ const int equal = left == right;
+ if (!equal) {
+ print_error("0x%x != 0x%x\n", left, right);
+ }
+ return equal;
+}
+
+/* Returns 1 if the specified values are not equal. If the values are equal
+ * an error is displayed and 0 is returned. */
+static int values_not_equal_display_error(const void* const left,
+ const void* const right) {
+ const int not_equal = left != right;
+ if (!not_equal) {
+ print_error("0x%x == 0x%x\n", left, right);
+ }
+ return not_equal;
+}
+
+
+/* Determine whether value is contained within check_integer_set.
+ * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is
+ * returned and an error is displayed. If invert is 1 and the value is not
+ * in the set 1 is returned, otherwise 0 is returned and an error is
+ * displayed. */
+static int value_in_set_display_error(
+ const void *value, const CheckIntegerSet * const check_integer_set,
+ const int invert) {
+ int succeeded = invert;
+ assert_true(check_integer_set);
+ {
+ const void ** const set = check_integer_set->set;
+ const size_t size_of_set = check_integer_set->size_of_set;
+ size_t i;
+ for (i = 0; i < size_of_set; i++) {
+ if (set[i] == value) {
+ if (invert) {
+ succeeded = 0;
+ }
+ break;
+ }
+ }
+ if (succeeded) {
+ return 1;
+ }
+ print_error("%d is %sin the set (", value, invert ? "" : "not ");
+ for (i = 0; i < size_of_set; i++) {
+ print_error("%d, ", set[i]);
+ }
+ print_error(")\n");
+ }
+ return 0;
+}
+
+
+/* Determine whether a value is within the specified range. If the value is
+ * within the specified range 1 is returned. If the value isn't within the
+ * specified range an error is displayed and 0 is returned. */
+static int integer_in_range_display_error(
+ const int value, const int range_min, const int range_max) {
+ if (value >= range_min && value <= range_max) {
+ return 1;
+ }
+ print_error("%d is not within the range %d-%d\n", value, range_min,
+ range_max);
+ return 0;
+}
+
+
+/* Determine whether a value is within the specified range. If the value
+ * is not within the range 1 is returned. If the value is within the
+ * specified range an error is displayed and zero is returned. */
+static int integer_not_in_range_display_error(
+ const int value, const int range_min, const int range_max) {
+ if (value < range_min || value > range_max) {
+ return 1;
+ }
+ print_error("%d is within the range %d-%d\n", value, range_min,
+ range_max);
+ return 0;
+}
+
+
+/* Determine whether the specified strings are equal. If the strings are equal
+ * 1 is returned. If they're not equal an error is displayed and 0 is
+ * returned. */
+static int string_equal_display_error(
+ const char * const left, const char * const right) {
+ if (strcmp(left, right) == 0) {
+ return 1;
+ }
+ print_error("\"%s\" != \"%s\"\n", left, right);
+ return 0;
+}
+
+
+/* Determine whether the specified strings are equal. If the strings are not
+ * equal 1 is returned. If they're not equal an error is displayed and 0 is
+ * returned */
+static int string_not_equal_display_error(
+ const char * const left, const char * const right) {
+ if (strcmp(left, right) != 0) {
+ return 1;
+ }
+ print_error("\"%s\" == \"%s\"\n", left, right);
+ return 0;
+}
+
+
+/* Determine whether the specified areas of memory are equal. If they're equal
+ * 1 is returned otherwise an error is displayed and 0 is returned. */
+static int memory_equal_display_error(const char* a, const char* b,
+ const size_t size) {
+ int differences = 0;
+ size_t i;
+ for (i = 0; i < size; i++) {
+ const char l = a[i];
+ const char r = b[i];
+ if (l != r) {
+ print_error("difference at offset %d 0x%02x 0x%02x\n", i, l, r);
+ differences ++;
+ }
+ }
+ if (differences) {
+ print_error("%d bytes of 0x%08x and 0x%08x differ\n", differences,
+ a, b);
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Determine whether the specified areas of memory are not equal. If they're
+ * not equal 1 is returned otherwise an error is displayed and 0 is
+ * returned. */
+static int memory_not_equal_display_error(const char* a, const char* b,
+ const size_t size) {
+ int same = 0;
+ size_t i;
+ for (i = 0; i < size; i++) {
+ const char l = a[i];
+ const char r = b[i];
+ if (l == r) {
+ print_error("equal at offset %d 0x%02x 0x%02x\n", i, l, r);
+ same ++;
+ }
+ }
+ if (same) {
+ print_error("%d bytes of 0x%08x and 0x%08x the same\n", same,
+ a, b);
+ return 0;
+ }
+ return 1;
+}
+
+
+// CheckParameterValue callback to check whether a value is within a set.
+static int check_in_set(const void *value, void *check_value_data) {
+ return value_in_set_display_error(value,
+ (CheckIntegerSet*)check_value_data, 0);
+}
+
+
+// CheckParameterValue callback to check whether a value isn't within a set.
+static int check_not_in_set(const void *value, void *check_value_data) {
+ return value_in_set_display_error(value,
+ (CheckIntegerSet*)check_value_data, 1);
+}
+
+
+/* Create the callback data for check_in_set() or check_not_in_set() and
+ * register a check event. */
+static void expect_set(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void *values[],
+ const size_t number_of_values,
+ const CheckParameterValue check_function, const int count) {
+ CheckIntegerSet * const check_integer_set =
+ malloc(sizeof(*check_integer_set) +
+ (sizeof(values[0]) * number_of_values));
+ void ** const set = (void**)(check_integer_set + 1);
+ assert_true(values);
+ assert_true(number_of_values);
+ memcpy(set, values, number_of_values * sizeof(values[0]));
+ check_integer_set->set = (const void**)set;
+ _expect_check(function, parameter, file, line, check_function,
+ check_integer_set, &check_integer_set->event, count);
+}
+
+
+// Add an event to check whether a value is in a set.
+void _expect_in_set(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void *values[],
+ const size_t number_of_values, const int count) {
+ expect_set(function, parameter, file, line, values, number_of_values,
+ check_in_set, count);
+}
+
+
+// Add an event to check whether a value isn't in a set.
+void _expect_not_in_set(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void *values[],
+ const size_t number_of_values, const int count) {
+ expect_set(function, parameter, file, line, values, number_of_values,
+ check_not_in_set, count);
+}
+
+
+// CheckParameterValue callback to check whether a value is within a range.
+static int check_in_range(const void *value, void *check_value_data) {
+ CheckIntegerRange * const check_integer_range = check_value_data;
+ assert_true(check_value_data);
+ return integer_in_range_display_error(
+ (int)value, check_integer_range->minimum,
+ check_integer_range->maximum);
+}
+
+
+// CheckParameterValue callback to check whether a value is not within a range.
+static int check_not_in_range(const void *value, void *check_value_data) {
+ CheckIntegerRange * const check_integer_range = check_value_data;
+ assert_true(check_value_data);
+ return integer_not_in_range_display_error(
+ (int)value, check_integer_range->minimum,
+ check_integer_range->maximum);
+}
+
+
+/* Create the callback data for check_in_range() or check_not_in_range() and
+ * register a check event. */
+static void expect_range(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line,
+ const int minimum, const int maximum,
+ const CheckParameterValue check_function, const int count) {
+ CheckIntegerRange * const check_integer_range =
+ malloc(sizeof(*check_integer_range));
+ check_integer_range->minimum = minimum;
+ check_integer_range->maximum = maximum;
+ _expect_check(function, parameter, file, line, check_function,
+ check_integer_range, &check_integer_range->event, count);
+}
+
+
+// Add an event to determine whether a parameter is within a range.
+void _expect_in_range(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line,
+ const int minimum, const int maximum, const int count) {
+ expect_range(function, parameter, file, line, minimum, maximum,
+ check_in_range, count);
+}
+
+
+// Add an event to determine whether a parameter is not within a range.
+void _expect_not_in_range(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line,
+ const int minimum, const int maximum, const int count) {
+ expect_range(function, parameter, file, line, minimum, maximum,
+ check_not_in_range, count);
+}
+
+
+/* CheckParameterValue callback to check whether a value is equal to an
+ * expected value. */
+static int check_value(const void *value, void *check_value_data) {
+ return values_equal_display_error(value, check_value_data);
+}
+
+
+// Add an event to check a parameter equals an expected value.
+void _expect_value(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void* const value,
+ const int count) {
+ _expect_check(function, parameter, file, line, check_value,
+ (void*)value, NULL, count);
+}
+
+
+/* CheckParameterValue callback to check whether a value is not equal to an
+ * expected value. */
+static int check_not_value(const void *value, void *check_value_data) {
+ return values_not_equal_display_error(value, check_value_data);
+}
+
+
+// Add an event to check a parameter is not equal to an expected value.
+void _expect_not_value(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void* const value,
+ const int count) {
+ _expect_check(function, parameter, file, line, check_not_value,
+ (void*)value, NULL, count);
+}
+
+
+// CheckParameterValue callback to check whether a parameter equals a string.
+static int check_string(const void * value, void *check_value_data) {
+ return string_equal_display_error(value, check_value_data);
+}
+
+
+// Add an event to check whether a parameter is equal to a string.
+void _expect_string(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const char* string,
+ const int count) {
+ _expect_check(function, parameter, file, line, check_string, (void*)string,
+ NULL, count);
+}
+
+
+/* CheckParameterValue callback to check whether a parameter is not equals to
+ * a string. */
+static int check_not_string(const void * value, void *check_value_data) {
+ return string_not_equal_display_error(value, check_value_data);
+}
+
+
+// Add an event to check whether a parameter is not equal to a string.
+void _expect_not_string(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const char* string,
+ const int count) {
+ _expect_check(function, parameter, file, line, check_not_string,
+ (void*)string, NULL, count);
+}
+
+/* CheckParameterValue callback to check whether a parameter equals an area of
+ * memory. */
+static int check_memory(const void* value, void *check_value_data) {
+ CheckMemoryData * const check = (CheckMemoryData*)check_value_data;
+ assert_true(check);
+ return memory_equal_display_error(value, check->memory, check->size);
+}
+
+
+/* Create the callback data for check_memory() or check_not_memory() and
+ * register a check event. */
+static void 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) {
+ CheckMemoryData * const check_data = malloc(sizeof(*check_data) + size);
+ void * const mem = (void*)(check_data + 1);
+ assert_true(memory);
+ assert_true(size);
+ memcpy(mem, memory, size);
+ check_data->memory = mem;
+ check_data->size = size;
+ _expect_check(function, parameter, file, line, check_function,
+ check_data, &check_data->event, count);
+}
+
+
+// Add an event to check whether a parameter matches an area of memory.
+void _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) {
+ expect_memory_setup(function, parameter, file, line, memory, size,
+ check_memory, count);
+}
+
+
+/* CheckParameterValue callback to check whether a parameter is not equal to
+ * an area of memory. */
+static int check_not_memory(const void* value, void *check_value_data) {
+ CheckMemoryData * const check = (CheckMemoryData*)check_value_data;
+ assert_true(check);
+ return memory_not_equal_display_error(value, check->memory, check->size);
+}
+
+
+// Add an event to check whether a parameter doesn't match an area of memory.
+void _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) {
+ expect_memory_setup(function, parameter, file, line, memory, size,
+ check_not_memory, count);
+}
+
+
+// CheckParameterValue callback that always returns 1.
+static int check_any(const void *value, void *check_value_data) {
+ return 1;
+}
+
+
+// Add an event to allow any value for a parameter.
+void _expect_any(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const int count) {
+ _expect_check(function, parameter, file, line, check_any, NULL, NULL,
+ count);
+}
+
+
+void _check_expected(
+ const char * const function_name, const char * const parameter_name,
+ const char* file, const int line, const void* value) {
+ void *result;
+ const char* symbols[] = {function_name, parameter_name};
+ const int rc = get_symbol_value(&global_function_parameter_map_head,
+ symbols, 2, &result);
+ if (rc) {
+ CheckParameterEvent * const check = (CheckParameterEvent*)result;
+ int check_succeeded;
+ global_last_parameter_location = check->location;
+ check_succeeded = check->check_value(value, check->check_value_data);
+ if (rc == 1) {
+ free(check);
+ }
+ if (!check_succeeded) {
+ print_error("ERROR: Check of parameter %s, function %s failed\n"
+ "Expected parameter declared at "
+ SOURCE_LOCATION_FORMAT "\n",
+ parameter_name, function_name,
+ global_last_parameter_location.file,
+ global_last_parameter_location.line);
+ _fail(file, line);
+ }
+ } else {
+ print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value "
+ "to check parameter %s of function %s\n", file, line,
+ parameter_name, function_name);
+ if (source_location_is_set(&global_last_parameter_location)) {
+ print_error("Previously declared parameter value was declared at "
+ SOURCE_LOCATION_FORMAT "\n",
+ global_last_parameter_location.file,
+ global_last_parameter_location.line);
+ } else {
+ print_error("There were no previously declared parameter values "
+ "for this test.\n");
+ }
+ exit_test(1);
+ }
+}
+
+
+// Replacement for assert.
+void mock_assert(const int result, const char* const expression,
+ const char* const file, const int line) {
+ if (!result) {
+ if (global_expecting_assert) {
+ longjmp(global_expect_assert_env, (int)expression);
+ } else {
+ print_error("ASSERT: %s\n", expression);
+ _fail(file, line);
+ }
+ }
+}
+
+
+void _assert_true(const int result, const char * const expression,
+ const char * const file, const int line) {
+ if (!result) {
+ print_error("%s\n", expression);
+ _fail(file, line);
+ }
+}
+
+void _assert_int_equal(const int a, const int b, const char * const file,
+ const int line) {
+ if (!values_equal_display_error((void*)a, (void*)b)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_int_not_equal(const int a, const int b, const char * const file,
+ const int line) {
+ if (!values_not_equal_display_error((void*)a, (void*)b)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_string_equal(const char * const a, const char * const b,
+ const char * const file, const int line) {
+ if (!string_equal_display_error(a, b)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_string_not_equal(const char * const a, const char * const b,
+ const char *file, const int line) {
+ if (!string_not_equal_display_error(a, b)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_memory_equal(const void * const a, const void * const b,
+ const size_t size, const char* const file,
+ const int line) {
+ if (!memory_equal_display_error((const char*)a, (const char*)b, size)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_memory_not_equal(const void * const a, const void * const b,
+ const size_t size, const char* const file,
+ const int line) {
+ if (!memory_not_equal_display_error((const char*)a, (const char*)b,
+ size)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_in_range(const int value, const int minimum, const int maximum,
+ const char* const file, const int line) {
+ if (!integer_in_range_display_error(value, minimum, maximum)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_not_in_range(const int value, const int minimum,
+ const int maximum, const char* const file,
+ const int line) {
+ if (!integer_not_in_range_display_error(value, minimum, maximum)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_in_set(const void* const value, const void *values[],
+ const size_t number_of_values, const char* const file,
+ const int line) {
+ CheckIntegerSet check_integer_set;
+ check_integer_set.set = values;
+ check_integer_set.size_of_set = number_of_values;
+ if (!value_in_set_display_error(value, &check_integer_set, 0)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_not_in_set(const void* const value, const void *values[],
+ const size_t number_of_values, const char* const file,
+ const int line) {
+ CheckIntegerSet check_integer_set;
+ check_integer_set.set = values;
+ check_integer_set.size_of_set = number_of_values;
+ if (!value_in_set_display_error(value, &check_integer_set, 1)) {
+ _fail(file, line);
+ }
+}
+
+
+// Get the list of allocated blocks.
+static ListNode* get_allocated_blocks_list() {
+ // If it initialized, initialize the list of allocated blocks.
+ if (!global_allocated_blocks.value) {
+ list_initialize(&global_allocated_blocks);
+ global_allocated_blocks.value = (void*)1;
+ }
+ return &global_allocated_blocks;
+}
+
+// Use the real malloc in this function.
+#undef malloc
+void* _test_malloc(const size_t size, const char* file, const int line) {
+ char* ptr;
+ MallocBlockInfo *block_info;
+ ListNode * const block_list = get_allocated_blocks_list();
+ const size_t allocate_size = size + (MALLOC_GUARD_SIZE * 2) +
+ sizeof(*block_info) + MALLOC_ALIGNMENT;
+ char* const block = (char*)malloc(allocate_size);
+ assert_true(block);
+
+ // Calculate the returned address.
+ ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE + sizeof(*block_info) +
+ MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1));
+
+ // Initialize the guard blocks.
+ memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
+ memset(ptr + size, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
+ memset(ptr, MALLOC_ALLOC_PATTERN, size);
+
+ block_info = (MallocBlockInfo*)(ptr - (MALLOC_GUARD_SIZE +
+ sizeof(*block_info)));
+ set_source_location(&block_info->location, file, line);
+ block_info->allocated_size = allocate_size;
+ block_info->size = size;
+ block_info->block = block;
+ block_info->node.value = block_info;
+ list_add(block_list, &block_info->node);
+ return ptr;
+}
+#define malloc test_malloc
+
+
+void* _test_calloc(const size_t number_of_elements, const size_t size,
+ const char* file, const int line) {
+ void* const ptr = _test_malloc(number_of_elements * size, file, line);
+ if (ptr) {
+ memset(ptr, 0, number_of_elements * size);
+ }
+ return ptr;
+}
+
+
+// Use the real free in this function.
+#undef free
+void _test_free(void* const ptr, const char* file, const int line) {
+ unsigned int i;
+ char *block = (char*)ptr;
+ MallocBlockInfo *block_info;
+ _assert_true((int)ptr, "ptr", file, line);
+ block_info = (MallocBlockInfo*)(block - (MALLOC_GUARD_SIZE +
+ sizeof(*block_info)));
+ // Check the guard blocks.
+ {
+ char *guards[2] = {block - MALLOC_GUARD_SIZE,
+ block + block_info->size};
+ for (i = 0; i < ARRAY_LENGTH(guards); i++) {
+ unsigned int j;
+ char * const guard = guards[i];
+ for (j = 0; j < MALLOC_GUARD_SIZE; j++) {
+ const char diff = guard[j] - MALLOC_GUARD_PATTERN;
+ if (diff) {
+ print_error(
+ "Guard block of 0x%08x size=%d allocated by "
+ SOURCE_LOCATION_FORMAT " at 0x%08x is corrupt\n",
+ (size_t)ptr, block_info->size,
+ block_info->location.file, block_info->location.line,
+ (size_t)&guard[j]);
+ _fail(file, line);
+ }
+ }
+ }
+ }
+ list_remove(&block_info->node, NULL, NULL);
+
+ block = block_info->block;
+ memset(block, MALLOC_FREE_PATTERN, block_info->allocated_size);
+ free(block);
+}
+#define free test_free
+
+
+// Crudely checkpoint the current heap state.
+static const ListNode* check_point_allocated_blocks() {
+ return get_allocated_blocks_list()->prev;
+}
+
+
+/* Display the blocks allocated after the specified check point. This
+ * function returns the number of blocks displayed. */
+static int display_allocated_blocks(const ListNode * const check_point) {
+ const ListNode * const head = get_allocated_blocks_list();
+ const ListNode *node;
+ int allocated_blocks = 0;
+ assert_true(check_point);
+ assert_true(check_point->next);
+
+ for (node = check_point->next; node != head; node = node->next) {
+ const MallocBlockInfo * const block_info = node->value;
+ assert_true(block_info);
+
+ if (!allocated_blocks) {
+ print_error("Blocks allocated...\n");
+ }
+ print_error(" 0x%08x : " SOURCE_LOCATION_FORMAT "\n",
+ block_info->block, block_info->location.file,
+ block_info->location.line);
+ allocated_blocks ++;
+ }
+ return allocated_blocks;
+}
+
+
+// Free all blocks allocated after the specified check point.
+static void free_allocated_blocks(const ListNode * const check_point) {
+ const ListNode * const head = get_allocated_blocks_list();
+ const ListNode *node;
+ assert_true(check_point);
+
+ node = check_point->next;
+ assert_true(node);
+
+ while (node != head) {
+ MallocBlockInfo * const block_info = (MallocBlockInfo*)node->value;
+ node = node->next;
+ free((char*)block_info + sizeof(*block_info) + MALLOC_GUARD_SIZE);
+ }
+}
+
+
+// Fail if any any blocks are allocated after the specified check point.
+static void fail_if_blocks_allocated(const ListNode * const check_point,
+ const char * const test_name) {
+ const int allocated_blocks = display_allocated_blocks(check_point);
+ if (allocated_blocks) {
+ free_allocated_blocks(check_point);
+ print_error("ERROR: %s leaked %d block(s)\n", test_name,
+ allocated_blocks);
+ exit_test(1);
+ }
+}
+
+
+void _fail(const char * const file, const int line) {
+ print_error("ERROR: " SOURCE_LOCATION_FORMAT " Failure!\n", file, line);
+ exit_test(1);
+}
+
+
+#ifndef _WIN32
+static void exception_handler(int sig) {
+ print_error("%s\n", strsignal(sig));
+ exit_test(1);
+}
+
+#else // _WIN32
+
+static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
+ EXCEPTION_RECORD * const exception_record =
+ exception_pointers->ExceptionRecord;
+ const DWORD code = exception_record->ExceptionCode;
+ unsigned int i;
+ for (i = 0; i < ARRAY_LENGTH(exception_codes); i++) {
+ const ExceptionCodeInfo * const code_info = &exception_codes[i];
+ if (code == code_info->code) {
+ static int shown_debug_message = 0;
+ fflush(stdout);
+ print_error("%s occurred at 0x%08x.\n", code_info->description,
+ exception_record->ExceptionAddress);
+ if (!shown_debug_message) {
+ print_error(
+ "\n"
+ "To debug in Visual Studio...\n"
+ "1. Select menu item File->Open Project\n"
+ "2. Change 'Files of type' to 'Executable Files'\n"
+ "3. Open this executable.\n"
+ "4. Select menu item Debug->Start\n"
+ "\n"
+ "Alternatively, set the environment variable \n"
+ "UNIT_TESTING_DEBUG to 1 and rebuild this executable, \n"
+ "then click 'Debug' in the popup dialog box.\n"
+ "\n");
+ shown_debug_message = 1;
+ }
+ exit_test(0);
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif // !_WIN32
+
+
+// Standard output and error print methods.
+void vprint_message(const char* const format, va_list args) {
+ char buffer[1024];
+ vsnprintf(buffer, sizeof(buffer), format, args);
+ printf(buffer);
+#ifdef _WIN32
+ OutputDebugString(buffer);
+#endif // _WIN32
+}
+
+
+void vprint_error(const char* const format, va_list args) {
+ char buffer[1024];
+ vsnprintf(buffer, sizeof(buffer), format, args);
+ fprintf(stderr, buffer);
+#ifdef _WIN32
+ OutputDebugString(buffer);
+#endif // _WIN32
+}
+
+
+void print_message(const char* const format, ...) {
+ va_list args;
+ va_start(args, format);
+ vprint_message(format, args);
+ va_end(args);
+}
+
+
+void print_error(const char* const format, ...) {
+ va_list args;
+ va_start(args, format);
+ vprint_error(format, args);
+ va_end(args);
+}
+
+
+int _run_test(
+ const char * const function_name, const UnitTestFunction Function,
+ void ** const state, const UnitTestFunctionType function_type,
+ const void* const heap_check_point) {
+ const ListNode * const check_point = heap_check_point ?
+ heap_check_point : check_point_allocated_blocks();
+ void *current_state = NULL;
+ int rc = 1;
+ int handle_exceptions = 1;
+#ifdef _WIN32
+ handle_exceptions = !IsDebuggerPresent();
+#endif // _WIN32
+#if UNIT_TESTING_DEBUG
+ handle_exceptions = 0;
+#endif // UNIT_TESTING_DEBUG
+
+ if (handle_exceptions) {
+#ifndef _WIN32
+ unsigned int i;
+ for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
+ default_signal_functions[i] = signal(
+ exception_signals[i], exception_handler);
+ }
+#else // _WIN32
+ previous_exception_filter = SetUnhandledExceptionFilter(
+ exception_filter);
+#endif // !_WIN32
+ }
+
+ if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
+ print_message("%s: Starting test\n", function_name);
+ }
+ initialize_testing(function_name);
+ global_running_test = 1;
+ if (setjmp(global_run_test_env) == 0) {
+ Function(state ? state : &current_state);
+ fail_if_leftover_values(function_name);
+
+ /* If this is a setup function then ignore any allocated blocks
+ * only ensure they're deallocated on tear down. */
+ if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) {
+ fail_if_blocks_allocated(check_point, function_name);
+ }
+
+ global_running_test = 0;
+
+ if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
+ print_message("%s: Test completed successfully.\n", function_name);
+ }
+ rc = 0;
+ } else {
+ global_running_test = 0;
+ print_message("%s: Test failed.\n", function_name);
+ }
+ teardown_testing(function_name);
+
+ if (handle_exceptions) {
+#ifndef _WIN32
+ unsigned int i;
+ for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) {
+ signal(exception_signals[i], default_signal_functions[i]);
+ }
+#else // _WIN32
+ if (previous_exception_filter) {
+ SetUnhandledExceptionFilter(previous_exception_filter);
+ previous_exception_filter = NULL;
+ }
+#endif // !_WIN32
+ }
+
+ return rc;
+}
+
+
+int _run_tests(const UnitTest * const tests, const size_t number_of_tests) {
+ // Whether to execute the next test.
+ int run_next_test = 1;
+ // Whether the previous test failed.
+ int previous_test_failed = 0;
+ // Check point of the heap state.
+ const ListNode * const check_point = check_point_allocated_blocks();
+ // Current test being executed.
+ size_t current_test = 0;
+ // Number of tests executed.
+ size_t tests_executed = 0;
+ // Number of failed tests.
+ size_t total_failed = 0;
+ // Number of setup functions.
+ size_t setups = 0;
+ // Number of teardown functions.
+ size_t teardowns = 0;
+ /* A stack of test states. A state is pushed on the stack
+ * when a test setup occurs and popped on tear down. */
+ TestState* test_states = malloc(number_of_tests * sizeof(*test_states));
+ size_t number_of_test_states = 0;
+ // Names of the tests that failed.
+ const char** failed_names = malloc(number_of_tests *
+ sizeof(*failed_names));
+ void **current_state = NULL;
+
+ while (current_test < number_of_tests) {
+ const ListNode *test_check_point = NULL;
+ TestState *current_TestState;
+ const UnitTest * const test = &tests[current_test++];
+ if (!test->function) {
+ continue;
+ }
+
+ switch (test->function_type) {
+ case UNIT_TEST_FUNCTION_TYPE_TEST:
+ run_next_test = 1;
+ break;
+ case UNIT_TEST_FUNCTION_TYPE_SETUP: {
+ // Checkpoint the heap before the setup.
+ current_TestState = &test_states[number_of_test_states++];
+ current_TestState->check_point = check_point_allocated_blocks();
+ test_check_point = current_TestState->check_point;
+ current_state = &current_TestState->state;
+ *current_state = NULL;
+ run_next_test = 1;
+ setups ++;
+ break;
+ }
+ case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
+ // Check the heap based on the last setup checkpoint.
+ assert_true(number_of_test_states);
+ current_TestState = &test_states[--number_of_test_states];
+ test_check_point = current_TestState->check_point;
+ current_state = &current_TestState->state;
+ teardowns ++;
+ break;
+ default:
+ print_error("Invalid unit test function type %d\n",
+ test->function_type);
+ exit_test(1);
+ break;
+ }
+
+ if (run_next_test) {
+ int failed = _run_test(test->name, test->function, current_state,
+ test->function_type, test_check_point);
+ if (failed) {
+ failed_names[total_failed] = test->name;
+ }
+
+ switch (test->function_type) {
+ case UNIT_TEST_FUNCTION_TYPE_TEST:
+ previous_test_failed = failed;
+ total_failed += failed;
+ tests_executed ++;
+ break;
+
+ case UNIT_TEST_FUNCTION_TYPE_SETUP:
+ if (failed) {
+ total_failed ++;
+ tests_executed ++;
+ // Skip forward until the next test or setup function.
+ run_next_test = 0;
+ }
+ previous_test_failed = 0;
+ break;
+
+ case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
+ // If this test failed.
+ if (failed && !previous_test_failed) {
+ total_failed ++;
+ }
+ break;
+ default:
+ assert_false("BUG: shouldn't be here!");
+ break;
+ }
+ }
+ }
+
+ if (total_failed) {
+ size_t i;
+ print_error("%d out of %d tests failed!\n", total_failed,
+ tests_executed);
+ for (i = 0; i < total_failed; i++) {
+ print_error(" %s\n", failed_names[i]);
+ }
+ } else {
+ print_message("All %d tests passed\n", tests_executed);
+ }
+
+ if (number_of_test_states) {
+ print_error("Mismatched number of setup %d and teardown %d "
+ "functions\n", setups, teardowns);
+ total_failed = -1;
+ }
+
+ free(test_states);
+ free((void*)failed_names);
+
+ fail_if_blocks_allocated(check_point, "run_tests");
+ return (int)total_failed;
+}
diff --git a/cmockery_0_1_2/src/config.h b/cmockery_0_1_2/src/config.h
new file mode 100644
index 0000000..bcc87fa
--- /dev/null
+++ b/cmockery_0_1_2/src/config.h
@@ -0,0 +1,137 @@
+/* src/config.h. Generated by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Namespace for Google classes */
+#define GOOGLE_NAMESPACE ::google
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `calloc' function. */
+#define HAVE_CALLOC 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `exit' function. */
+#define HAVE_EXIT 1
+
+/* Define to 1 if you have the `fprintf' function. */
+#define HAVE_FPRINTF 1
+
+/* Define to 1 if you have the `free' function. */
+#define HAVE_FREE 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `longjmp' function. */
+#define HAVE_LONGJMP 1
+
+/* Define to 1 if you have the `malloc' function. */
+#define HAVE_MALLOC 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* define if the compiler implements namespaces */
+#define HAVE_NAMESPACES 1
+
+/* Define to 1 if you have the `printf' function. */
+#define HAVE_PRINTF 1
+
+/* Define to 1 if you have the `setjmp' function. */
+#define HAVE_SETJMP 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `signal' function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcmp' function. */
+#define HAVE_STRCMP 1
+
+/* Define to 1 if you have the `strcpy' function. */
+#define HAVE_STRCPY 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Name of package */
+#define PACKAGE "cmockery"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "cmockery"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "cmockery 0.1.2"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "cmockery"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.1.2"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Version number of package */
+#define VERSION "0.1.2"
+
+/* Stops putting the code inside the Google namespace */
+#define _END_GOOGLE_NAMESPACE_ }
+
+/* Puts following code inside the Google namespace */
+#define _START_GOOGLE_NAMESPACE_ namespace google {
diff --git a/cmockery_0_1_2/src/config.h.in b/cmockery_0_1_2/src/config.h.in
new file mode 100644
index 0000000..802d225
--- /dev/null
+++ b/cmockery_0_1_2/src/config.h.in
@@ -0,0 +1,136 @@
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Namespace for Google classes */
+#undef GOOGLE_NAMESPACE
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the `calloc' function. */
+#undef HAVE_CALLOC
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `exit' function. */
+#undef HAVE_EXIT
+
+/* Define to 1 if you have the `fprintf' function. */
+#undef HAVE_FPRINTF
+
+/* Define to 1 if you have the `free' function. */
+#undef HAVE_FREE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `longjmp' function. */
+#undef HAVE_LONGJMP
+
+/* Define to 1 if you have the `malloc' function. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* define if the compiler implements namespaces */
+#undef HAVE_NAMESPACES
+
+/* Define to 1 if you have the `printf' function. */
+#undef HAVE_PRINTF
+
+/* Define to 1 if you have the `setjmp' function. */
+#undef HAVE_SETJMP
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#undef HAVE_SETJMP_H
+
+/* Define to 1 if you have the `signal' function. */
+#undef HAVE_SIGNAL
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcmp' function. */
+#undef HAVE_STRCMP
+
+/* Define to 1 if you have the `strcpy' function. */
+#undef HAVE_STRCPY
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* the namespace where STL code like vector<> is defined */
+#undef STL_NAMESPACE
+
+/* Version number of package */
+#undef VERSION
+
+/* Stops putting the code inside the Google namespace */
+#undef _END_GOOGLE_NAMESPACE_
+
+/* Puts following code inside the Google namespace */
+#undef _START_GOOGLE_NAMESPACE_
diff --git a/cmockery_0_1_2/src/example/allocate_module.c b/cmockery_0_1_2/src/example/allocate_module.c
new file mode 100644
index 0000000..dda7260
--- /dev/null
+++ b/cmockery_0_1_2/src/example/allocate_module.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+
+#if UNIT_TESTING
+extern void* _test_malloc(const size_t size, const char* file, const int line);
+extern void* _test_calloc(const size_t number_of_elements, const size_t size,
+ const char* file, const int line);
+extern void _test_free(void* const ptr, const char* file, const int line);
+
+#define malloc(size) _test_malloc(size, __FILE__, __LINE__)
+#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
+#define free(ptr) _test_free(ptr, __FILE__, __LINE__)
+#endif // UNIT_TESTING
+
+void leak_memory() {
+ int * const temporary = (int*)malloc(sizeof(int));
+ *temporary = 0;
+}
+
+void buffer_overflow() {
+ char * const memory = (char*)malloc(sizeof(int));
+ memory[sizeof(int)] = '!';
+ free(memory);
+}
+
+void buffer_underflow() {
+ char * const memory = (char*)malloc(sizeof(int));
+ memory[-1] = '!';
+ free(memory);
+}
diff --git a/cmockery_0_1_2/src/example/allocate_module_test.c b/cmockery_0_1_2/src/example/allocate_module_test.c
new file mode 100644
index 0000000..f7d6079
--- /dev/null
+++ b/cmockery_0_1_2/src/example/allocate_module_test.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmockery.h>
+
+extern void leak_memory();
+extern void buffer_overflow();
+extern void buffer_underflow();
+
+// Test case that fails as leak_memory() leaks a dynamically allocated block.
+void leak_memory_test(void **state) {
+ leak_memory();
+}
+
+// Test case that fails as buffer_overflow() corrupts an allocated block.
+void buffer_overflow_test(void **state) {
+ buffer_overflow();
+}
+
+// Test case that fails as buffer_underflow() corrupts an allocated block.
+void buffer_underflow_test(void **state) {
+ buffer_underflow();
+}
+
+int main(int argc, char* argv[]) {
+ const UnitTest tests[] = {
+ unit_test(leak_memory_test),
+ unit_test(buffer_overflow_test),
+ unit_test(buffer_underflow_test),
+ };
+ return run_tests(tests);
+}
diff --git a/cmockery_0_1_2/src/example/assert_macro.c b/cmockery_0_1_2/src/example/assert_macro.c
new file mode 100644
index 0000000..aadcac3
--- /dev/null
+++ b/cmockery_0_1_2/src/example/assert_macro.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+
+static const char* status_code_strings[] = {
+ "Address not found",
+ "Connection dropped",
+ "Connection timed out",
+};
+
+const char* get_status_code_string(const unsigned int status_code) {
+ return status_code_strings[status_code];
+};
+
+unsigned int string_to_status_code(const char* const status_code_string) {
+ unsigned int i;
+ for (i = 0; i < sizeof(status_code_string) / sizeof(status_code_string[0]);
+ i++) {
+ if (strcmp(status_code_strings[i], status_code_string) == 0) {
+ return i;
+ }
+ }
+ return ~0U;
+}
diff --git a/cmockery_0_1_2/src/example/assert_macro_test.c b/cmockery_0_1_2/src/example/assert_macro_test.c
new file mode 100644
index 0000000..0df8f96
--- /dev/null
+++ b/cmockery_0_1_2/src/example/assert_macro_test.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmockery.h>
+
+extern const char* get_status_code_string(const unsigned int status_code);
+extern unsigned int string_to_status_code(
+ const char* const status_code_string);
+
+/* This test will fail since the string returned by get_status_code_string(0)
+ * doesn't match "Connection timed out". */
+void get_status_code_string_test(void **state) {
+ assert_string_equal(get_status_code_string(0), "Address not found");
+ assert_string_equal(get_status_code_string(1), "Connection timed out");
+}
+
+// This test will fail since the status code of "Connection timed out" isn't 1
+void string_to_status_code_test(void **state) {
+ assert_int_equal(string_to_status_code("Address not found"), 0);
+ assert_int_equal(string_to_status_code("Connection timed out"), 1);
+}
+
+int main(int argc, char *argv[]) {
+ const UnitTest tests[] = {
+ unit_test(get_status_code_string_test),
+ unit_test(string_to_status_code_test),
+ };
+ return run_tests(tests);
+}
diff --git a/cmockery_0_1_2/src/example/calculator.c b/cmockery_0_1_2/src/example/calculator.c
new file mode 100644
index 0000000..da3775b
--- /dev/null
+++ b/cmockery_0_1_2/src/example/calculator.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// A calculator example used to demonstrate the cmockery testing library.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// If this is being built for a unit test.
+#if UNIT_TESTING
+
+/* Redirect printf to a function in the test application so it's possible to
+ * test the standard output. */
+#ifdef printf
+#undef printf
+#endif // printf
+#define printf example_test_printf
+
+extern void print_message(const char *format, ...);
+
+/* Redirect fprintf to a function in the test application so it's possible to
+ * test error messages. */
+#ifdef fprintf
+#undef fprintf
+#endif // fprintf
+#define fprintf example_test_fprintf
+
+extern int example_test_fprintf(FILE * const file, const char *format, ...);
+
+// Redirect assert to mock_assert() so assertions can be caught by cmockery.
+#ifdef assert
+#undef assert
+#endif // assert
+#define assert(expression) \
+ mock_assert((int)(expression), #expression, __FILE__, __LINE__)
+void mock_assert(const int result, const char* expression, const char *file,
+ const int line);
+
+/* Redirect calloc and free to test_calloc() and test_free() so cmockery can
+ * check for memory leaks. */
+#ifdef calloc
+#undef calloc
+#endif // calloc
+#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
+#ifdef free
+#undef free
+#endif // free
+#define free(ptr) _test_free(ptr, __FILE__, __LINE__)
+void* _test_calloc(const size_t number_of_elements, const size_t size,
+ const char* file, const int line);
+void _test_free(void* const ptr, const char* file, const int line);
+
+/* main is defined in the unit test so redefine name of the the main function
+ * here. */
+#define main example_main
+
+/* All functions in this object need to be exposed to the test application,
+ * so redefine static to nothing. */
+#define static
+
+#endif // UNIT_TESTING
+
+
+// A binary arithmetic integer operation (add, subtract etc.)
+typedef int (*BinaryOperator)(int a, int b);
+
+// Structure which maps operator strings to functions.
+typedef struct OperatorFunction {
+ const char* operator;
+ BinaryOperator function;
+} OperatorFunction;
+
+
+static int add(int a, int b);
+static int subtract(int a, int b);
+static int multiply(int a, int b);
+static int divide(int a, int b);
+
+// Associate operator strings to functions.
+static OperatorFunction operator_function_map[] = {
+ {"+", add},
+ {"-", subtract},
+ {"*", multiply},
+ {"/", divide},
+};
+
+static int add(int a, int b) {
+ return a + b;
+}
+
+static int subtract(int a, int b) {
+ return a - b;
+}
+
+static int multiply(int a, int b) {
+ return a * b;
+}
+
+static int divide(int a, int b) {
+ assert(b); // Check for divde by zero.
+ return a / b;
+}
+
+/* Searches the specified array of operator_functions for the function
+ * associated with the specified operator_string. This function returns the
+ * function associated with operator_string if successful, NULL otherwise.
+ */
+static BinaryOperator find_operator_function_by_string(
+ const size_t number_of_operator_functions,
+ const OperatorFunction * const operator_functions,
+ const char* const operator_string) {
+ size_t i;
+ assert(!number_of_operator_functions || operator_functions);
+ assert(operator_string);
+
+ for (i = 0; i < number_of_operator_functions; i++) {
+ const OperatorFunction *const operator_function =
+ &operator_functions[i];
+ if (strcmp(operator_function->operator, operator_string) == 0) {
+ return operator_function->function;
+ }
+ }
+ return NULL;
+}
+
+/* Perform a series of binary arithmetic integer operations with no operator
+ * precedence.
+ *
+ * The input expression is specified by arguments which is an array of
+ * containing number_of_arguments strings. Operators invoked by the expression
+ * are specified by the array operator_functions containing
+ * number_of_operator_functions, OperatorFunction structures. The value of
+ * each binary operation is stored in a pointer returned to intermediate_values
+ * which is allocated by malloc().
+ *
+ * If successful, this function returns the integer result of the operations.
+ * If an error occurs while performing the operation error_occurred is set to
+ * 1, the operation is aborted and 0 is returned.
+ */
+static int perform_operation(
+ int number_of_arguments, char *arguments[],
+ const size_t number_of_operator_functions,
+ const OperatorFunction * const operator_functions,
+ int * const number_of_intermediate_values,
+ int ** const intermediate_values, int * const error_occurred) {
+ char *end_of_integer;
+ int value;
+ unsigned int i;
+ assert(!number_of_arguments || arguments);
+ assert(!number_of_operator_functions || operator_functions);
+ assert(error_occurred);
+ assert(number_of_intermediate_values);
+ assert(intermediate_values);
+
+ *error_occurred = 0;
+ *number_of_intermediate_values = 0;
+ *intermediate_values = NULL;
+ if (!number_of_arguments)
+ return 0;
+
+ // Parse the first value.
+ value = (int)strtol(arguments[0], &end_of_integer, 10);
+ if (end_of_integer == arguments[0]) {
+ // If an error occurred while parsing the integer.
+ fprintf(stderr, "Unable to parse integer from argument %s\n",
+ arguments[0]);
+ *error_occurred = 1;
+ return 0;
+ }
+
+ // Allocate an array for the output values.
+ *intermediate_values = calloc(((number_of_arguments - 1) / 2),
+ sizeof(**intermediate_values));
+
+ i = 1;
+ while (i < number_of_arguments) {
+ int other_value;
+ const char* const operator_string = arguments[i];
+ const BinaryOperator function = find_operator_function_by_string(
+ number_of_operator_functions, operator_functions, operator_string);
+ int * const intermediate_value =
+ &((*intermediate_values)[*number_of_intermediate_values]);
+ (*number_of_intermediate_values) ++;
+
+ if (!function) {
+ fprintf(stderr, "Unknown operator %s, argument %d\n",
+ operator_string, i);
+ *error_occurred = 1;
+ break;
+ }
+ i ++;
+
+ if (i == number_of_arguments) {
+ fprintf(stderr, "Binary operator %s missing argument\n",
+ operator_string);
+ *error_occurred = 1;
+ break;
+ }
+
+ other_value = (int)strtol(arguments[i], &end_of_integer, 10);
+ if (end_of_integer == arguments[i]) {
+ // If an error occurred while parsing the integer.
+ fprintf(stderr, "Unable to parse integer %s of argument %d\n",
+ arguments[i], i);
+ *error_occurred = 1;
+ break;
+ }
+ i ++;
+
+ // Perform the operation and store the intermediate value.
+ *intermediate_value = function(value, other_value);
+ value = *intermediate_value;
+ }
+ if (*error_occurred) {
+ free(*intermediate_values);
+ *intermediate_values = NULL;
+ *number_of_intermediate_values = 0;
+ return 0;
+ }
+ return value;
+}
+
+int main(int argc, char *argv[]) {
+ int return_value;
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ // Peform the operation.
+ const int result = perform_operation(
+ argc - 1, &argv[1],
+ sizeof(operator_function_map) / sizeof(operator_function_map[0]),
+ operator_function_map, &number_of_intermediate_values,
+ &intermediate_values, &return_value);
+
+ // If no errors occurred display the result.
+ if (!return_value && argc > 1) {
+ unsigned int i;
+ unsigned int intermediate_value_index = 0;
+ printf("%s\n", argv[1]);
+ for (i = 2; i < argc; i += 2) {
+ assert(intermediate_value_index < number_of_intermediate_values);
+ printf(" %s %s = %d\n", argv[i], argv[i + 1],
+ intermediate_values[intermediate_value_index++]);
+ }
+ printf("= %d\n", result);
+ }
+ if (intermediate_values) {
+ free(intermediate_values);
+ }
+
+ return return_value;
+}
diff --git a/cmockery_0_1_2/src/example/calculator_test.c b/cmockery_0_1_2/src/example/calculator_test.c
new file mode 100644
index 0000000..6feaf41
--- /dev/null
+++ b/cmockery_0_1_2/src/example/calculator_test.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include "cmockery.h"
+#include <stdio.h>
+
+#ifdef _WIN32
+// Compatibility with the Windows standard C library.
+#define vsnprintf _vsnprintf
+#endif // _WIN32
+
+#define array_length(x) (sizeof(x) / sizeof((x)[0]))
+
+/* To simplify this code, these functions and data structures could have been
+ * separated out from the application example.c into a header shared with
+ * test application. However, this example illustrates how it's possible to
+ * test existing code with little modification. */
+
+typedef int (*BinaryOperator)(int a, int b);
+
+typedef struct OperatorFunction {
+ const char* operator;
+ BinaryOperator function;
+} OperatorFunction;
+
+extern int add(int a, int b);
+extern int subtract(int a, int b);
+extern int multiply(int a, int b);
+extern int divide(int a, int b);
+extern BinaryOperator find_operator_function_by_string(
+ const size_t number_of_operator_functions,
+ const OperatorFunction * const operator_functions,
+ const char* const operator_string);
+extern int perform_operation(
+ int number_of_arguments, char *arguments[],
+ const size_t number_of_operator_functions,
+ const OperatorFunction * const operator_functions,
+ int * const number_of_intermediate_values,
+ int ** const intermediate_values, int * const error_occurred);
+extern int example_main(int argc, char *argv[]);
+
+/* A mock fprintf function that checks the value of strings printed to the
+ * standard error stream. */
+int example_test_fprintf(FILE* const file, const char *format, ...) {
+ int return_value;
+ va_list args;
+ char temporary_buffer[256];
+ assert_true(file == stderr);
+ va_start(args, format);
+ return_value = vsnprintf(temporary_buffer, sizeof(temporary_buffer),
+ format, args);
+ check_expected(temporary_buffer);
+ va_end(args);
+ return return_value;
+}
+
+/* A mock printf function that checks the value of strings printed to the
+ * standard output stream. */
+int example_test_printf(const char *format, ...) {
+ int return_value;
+ va_list args;
+ char temporary_buffer[256];
+ va_start(args, format);
+ return_value = vsnprintf(temporary_buffer, sizeof(temporary_buffer),
+ format, args);
+ check_expected(temporary_buffer);
+ va_end(args);
+ return return_value;
+}
+
+// A mock binary operator function.
+int binary_operator(int a, int b) {
+ check_expected(a);
+ check_expected(b);
+ return (int)mock();
+}
+
+
+// Ensure add() adds two integers correctly.
+void test_add(void **state) {
+ assert_int_equal(add(3, 3), 6);
+ assert_int_equal(add(3, -3), 0);
+}
+
+// Ensure subtract() subtracts two integers correctly.
+void test_subtract(void **state) {
+ assert_int_equal(subtract(3, 3), 0);
+ assert_int_equal(subtract(3, -3), 6);
+}
+
+// Ensure multiple() mulitplies two integers correctly.
+void test_multiply(void **state) {
+ assert_int_equal(multiply(3, 3), 9);
+ assert_int_equal(multiply(3, 0), 0);
+}
+
+// Ensure divide() divides one integer by another correctly.
+void test_divide(void **state) {
+ assert_int_equal(divide(10, 2), 5);
+ assert_int_equal(divide(2, 10), 0);
+}
+
+// Ensure divide() asserts when trying to divide by zero.
+void test_divide_by_zero(void **state) {
+ expect_assert_failure(divide(100, 0));
+}
+
+/* Ensure find_operator_function_by_string() asserts when a NULL pointer is
+ * specified as the table to search. */
+void test_find_operator_function_by_string_null_functions(void **state) {
+ expect_assert_failure(find_operator_function_by_string(1, NULL, "test"));
+}
+
+/* Ensure find_operator_function_by_string() asserts when a NULL pointer is
+ * specified as the string to search for. */
+void test_find_operator_function_by_string_null_string(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ expect_assert_failure(find_operator_function_by_string(
+ array_length(operator_functions), operator_functions, NULL));
+}
+
+/* Ensure find_operator_function_by_string() returns NULL when a NULL pointer
+ * is specified as the table to search when the table size is 0. */
+void test_find_operator_function_by_string_valid_null_functions(void **state) {
+ assert_int_equal((int)find_operator_function_by_string(0, NULL, "test"),
+ (int)NULL);
+}
+
+/* Ensure find_operator_function_by_string() returns NULL when searching for
+ * an operator string that isn't in the specified table. */
+void test_find_operator_function_by_string_not_found(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ {"-", binary_operator},
+ {"/", binary_operator},
+ };
+ assert_int_equal((int)find_operator_function_by_string(
+ array_length(operator_functions), operator_functions, "test"),
+ (int)NULL);
+}
+
+/* Ensure find_operator_function_by_string() returns the correct function when
+ * searching for an operator string that is in the specified table. */
+void test_find_operator_function_by_string_found(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", (BinaryOperator)0x12345678},
+ {"-", (BinaryOperator)0xDEADBEEF},
+ {"/", (BinaryOperator)0xABADCAFE},
+ };
+ assert_int_equal((int)find_operator_function_by_string(
+ array_length(operator_functions), operator_functions, "-"),
+ 0xDEADBEEF);
+}
+
+// Ensure perform_operation() asserts when a NULL arguments array is specified.
+void test_perform_operation_null_args(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+ expect_assert_failure(perform_operation(
+ 1, NULL, array_length(operator_functions), operator_functions,
+ &number_of_intermediate_values, &intermediate_values,
+ &error_occurred));
+}
+
+/* Ensure perform_operation() asserts when a NULL operator_functions array is
+ * specified. */
+void test_perform_operation_null_operator_functions(void **state) {
+ char *args[] = {
+ "1", "+", "2", "*", "4"
+ };
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+ expect_assert_failure(perform_operation(
+ array_length(args), args, 1, NULL, &number_of_intermediate_values,
+ &intermediate_values, &error_occurred));
+}
+
+/* Ensure perform_operation() asserts when a NULL pointer is specified for
+ * number_of_intermediate_values. */
+void test_perform_operation_null_number_of_intermediate_values(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ char *args[] = {
+ "1", "+", "2", "*", "4"
+ };
+ int *intermediate_values;
+ int error_occurred;
+ expect_assert_failure(perform_operation(
+ array_length(args), args, 1, operator_functions, NULL,
+ &intermediate_values, &error_occurred));
+}
+
+/* Ensure perform_operation() asserts when a NULL pointer is specified for
+ * intermediate_values. */
+void test_perform_operation_null_intermediate_values(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ char *args[] = {
+ "1", "+", "2", "*", "4"
+ };
+ int number_of_intermediate_values;
+ int error_occurred;
+ expect_assert_failure(perform_operation(
+ array_length(args), args, array_length(operator_functions),
+ operator_functions, &number_of_intermediate_values, NULL,
+ &error_occurred));
+}
+
+// Ensure perform_operation() returns 0 when no arguments are specified.
+void test_perform_operation_no_arguments(void **state) {
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+ assert_int_equal(perform_operation(
+ 0, NULL, 0, NULL, &number_of_intermediate_values, &intermediate_values,
+ &error_occurred), 0);
+ assert_int_equal(error_occurred, 0);
+}
+
+/* Ensure perform_operation() returns an error if the first argument isn't
+ * an integer string. */
+void test_perform_operation_first_arg_not_integer(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ char *args[] = {
+ "test", "+", "2", "*", "4"
+ };
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+
+ expect_string(example_test_fprintf, temporary_buffer,
+ "Unable to parse integer from argument test\n");
+
+ assert_int_equal(perform_operation(
+ array_length(args), args, array_length(operator_functions),
+ operator_functions, &number_of_intermediate_values,
+ &intermediate_values, &error_occurred), 0);
+ assert_int_equal(error_occurred, 1);
+}
+
+/* Ensure perform_operation() returns an error when parsing an unknown
+ * operator. */
+void test_perform_operation_unknown_operator(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ char *args[] = {
+ "1", "*", "2", "*", "4"
+ };
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+
+ expect_string(example_test_fprintf, temporary_buffer,
+ "Unknown operator *, argument 1\n");
+
+ assert_int_equal(perform_operation(
+ array_length(args), args, array_length(operator_functions),
+ operator_functions, &number_of_intermediate_values,
+ &intermediate_values, &error_occurred), 0);
+ assert_int_equal(error_occurred, 1);
+}
+
+/* Ensure perform_operation() returns an error when nothing follows an
+ * operator. */
+void test_perform_operation_missing_argument(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ char *args[] = {
+ "1", "+",
+ };
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+
+ expect_string(example_test_fprintf, temporary_buffer,
+ "Binary operator + missing argument\n");
+
+ assert_int_equal(perform_operation(
+ array_length(args), args, array_length(operator_functions),
+ operator_functions, &number_of_intermediate_values,
+ &intermediate_values, &error_occurred), 0);
+ assert_int_equal(error_occurred, 1);
+}
+
+/* Ensure perform_operation() returns an error when an integer doesn't follow
+ * an operator. */
+void test_perform_operation_no_integer_after_operator(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ };
+ char *args[] = {
+ "1", "+", "test",
+ };
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+
+ expect_string(example_test_fprintf, temporary_buffer,
+ "Unable to parse integer test of argument 2\n");
+
+ assert_int_equal(perform_operation(
+ array_length(args), args, array_length(operator_functions),
+ operator_functions, &number_of_intermediate_values,
+ &intermediate_values, &error_occurred), 0);
+ assert_int_equal(error_occurred, 1);
+}
+
+
+// Ensure perform_operation() succeeds given valid input parameters.
+void test_perform_operation(void **state) {
+ const OperatorFunction operator_functions[] = {
+ {"+", binary_operator},
+ {"*", binary_operator},
+ };
+ char *args[] = {
+ "1", "+", "3", "*", "10",
+ };
+ int number_of_intermediate_values;
+ int *intermediate_values;
+ int error_occurred;
+
+ // Setup return values of mock operator functions.
+ // Addition.
+ expect_value(binary_operator, a, 1);
+ expect_value(binary_operator, b, 3);
+ will_return(binary_operator, 4);
+
+ // Multiplication.
+ expect_value(binary_operator, a, 4);
+ expect_value(binary_operator, b, 10);
+ will_return(binary_operator, 40);
+
+ assert_int_equal(perform_operation(
+ array_length(args), args, array_length(operator_functions),
+ operator_functions, &number_of_intermediate_values,
+ &intermediate_values, &error_occurred), 40);
+ assert_int_equal(error_occurred, 0);
+
+ assert_true(intermediate_values);
+ assert_int_equal(intermediate_values[0], 4);
+ assert_int_equal(intermediate_values[1], 40);
+ test_free(intermediate_values);
+}
+
+
+// Ensure main() in example.c succeeds given no arguments.
+void test_example_main_no_args(void **state) {
+ char *args[] = {
+ "example",
+ };
+ assert_int_equal(example_main(array_length(args), args), 0);
+}
+
+
+
+// Ensure main() in example.c succeeds given valid input arguments.
+void test_example_main(void **state) {
+ char *args[] = {
+ "example", "1", "+", "3", "*", "10",
+ };
+
+ expect_string(example_test_printf, temporary_buffer, "1\n");
+ expect_string(example_test_printf, temporary_buffer, " + 3 = 4\n");
+ expect_string(example_test_printf, temporary_buffer, " * 10 = 40\n");
+ expect_string(example_test_printf, temporary_buffer, "= 40\n");
+
+ assert_int_equal(example_main(array_length(args), args), 0);
+}
+
+
+int main(int argc, char* argv[]) {
+ UnitTest tests[] = {
+ unit_test(test_add),
+ unit_test(test_subtract),
+ unit_test(test_multiply),
+ unit_test(test_divide),
+ unit_test(test_divide_by_zero),
+ unit_test(test_find_operator_function_by_string_null_functions),
+ unit_test(test_find_operator_function_by_string_null_string),
+ unit_test(test_find_operator_function_by_string_valid_null_functions),
+ unit_test(test_find_operator_function_by_string_not_found),
+ unit_test(test_find_operator_function_by_string_found),
+ unit_test(test_perform_operation_null_args),
+ unit_test(test_perform_operation_null_operator_functions),
+ unit_test(test_perform_operation_null_number_of_intermediate_values),
+ unit_test(test_perform_operation_null_intermediate_values),
+ unit_test(test_perform_operation_no_arguments),
+ unit_test(test_perform_operation_first_arg_not_integer),
+ unit_test(test_perform_operation_unknown_operator),
+ unit_test(test_perform_operation_missing_argument),
+ unit_test(test_perform_operation_no_integer_after_operator),
+ unit_test(test_perform_operation),
+ unit_test(test_example_main_no_args),
+ unit_test(test_example_main),
+ };
+ return run_tests(tests);
+}
diff --git a/cmockery_0_1_2/src/example/customer_database.c b/cmockery_0_1_2/src/example/customer_database.c
new file mode 100644
index 0000000..1cfce7e
--- /dev/null
+++ b/cmockery_0_1_2/src/example/customer_database.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include <database.h>
+#ifdef _WIN32
+#define snprintf _snprintf
+#endif // _WIN32
+
+// Connect to the database containing customer information.
+DatabaseConnection* connect_to_customer_database() {
+ return connect_to_database("customers.abcd.org", 321);
+}
+
+/* Find the ID of a customer by his/her name returning a value > 0 if
+ * successful, 0 otherwise. */
+unsigned int get_customer_id_by_name(
+ DatabaseConnection * const connection,
+ const char * const customer_name) {
+ char query_string[256];
+ int number_of_results;
+ void **results;
+ snprintf(query_string, sizeof(query_string),
+ "SELECT ID FROM CUSTOMERS WHERE NAME = %s", customer_name);
+ number_of_results = connection->query_database(connection, query_string,
+ &results);
+ if (number_of_results != 1) {
+ return -1;
+ }
+ return (unsigned int)results[0];
+}
diff --git a/cmockery_0_1_2/src/example/customer_database_test.c b/cmockery_0_1_2/src/example/customer_database_test.c
new file mode 100644
index 0000000..b059007
--- /dev/null
+++ b/cmockery_0_1_2/src/example/customer_database_test.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmockery.h>
+#include <database.h>
+
+extern DatabaseConnection* connect_to_customer_database();
+extern unsigned int get_customer_id_by_name(
+ DatabaseConnection * const connection, const char * const customer_name);
+
+// Mock query database function.
+unsigned int mock_query_database(
+ DatabaseConnection* const connection, const char * const query_string,
+ void *** const results) {
+ *results = (void**)mock();
+ return (unsigned int)mock();
+}
+
+// Mock of the connect to database function.
+DatabaseConnection* connect_to_database(const char * const database_url,
+ const unsigned int port) {
+ return (DatabaseConnection*)mock();
+}
+
+void test_connect_to_customer_database(void **state) {
+ will_return(connect_to_database, 0x0DA7ABA53);
+ assert_int_equal((int)connect_to_customer_database(), 0x0DA7ABA53);
+}
+
+/* This test fails as the mock function connect_to_database() will have no
+ * value to return. */
+void fail_connect_to_customer_database(void **state) {
+ assert_true(connect_to_customer_database() ==
+ (DatabaseConnection*)0x0DA7ABA53);
+}
+
+void test_get_customer_id_by_name(void **state) {
+ DatabaseConnection connection = {
+ "somedatabase.somewhere.com", 12345678, mock_query_database
+ };
+ // Return a single customer ID when mock_query_database() is called.
+ int customer_ids = 543;
+ will_return(mock_query_database, &customer_ids);
+ will_return(mock_query_database, 1);
+ assert_int_equal(get_customer_id_by_name(&connection, "john doe"), 543);
+}
+
+int main(int argc, char* argv[]) {
+ const UnitTest tests[] = {
+ unit_test(test_connect_to_customer_database),
+ unit_test(test_get_customer_id_by_name),
+ };
+ return run_tests(tests);
+}
diff --git a/cmockery_0_1_2/src/example/database.h b/cmockery_0_1_2/src/example/database.h
new file mode 100644
index 0000000..f6f6a43
--- /dev/null
+++ b/cmockery_0_1_2/src/example/database.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+typedef struct DatabaseConnection DatabaseConnection;
+
+/* Function that takes an SQL query string and sets results to an array of
+ * pointers with the result of the query. The value returned specifies the
+ * number of items in the returned array of results. The returned array of
+ * results are statically allocated and should not be deallocated using free()
+ */
+typedef unsigned int (*QueryDatabase)(
+ DatabaseConnection* const connection, const char * const query_string,
+ void *** const results);
+
+// Connection to a database.
+struct DatabaseConnection {
+ const char *url;
+ unsigned int port;
+ QueryDatabase query_database;
+};
+
+// Connect to a database.
+DatabaseConnection* connect_to_database(const char * const url,
+ const unsigned int port);
+
diff --git a/cmockery_0_1_2/src/example/key_value.c b/cmockery_0_1_2/src/example/key_value.c
new file mode 100644
index 0000000..00e1bc4
--- /dev/null
+++ b/cmockery_0_1_2/src/example/key_value.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct KeyValue {
+ unsigned int key;
+ const char* value;
+} KeyValue;
+
+static KeyValue *key_values = NULL;
+static unsigned int number_of_key_values = 0;
+
+void set_key_values(KeyValue * const new_key_values,
+ const unsigned int new_number_of_key_values) {
+ key_values = new_key_values;
+ number_of_key_values = new_number_of_key_values;
+}
+
+// Compare two key members of KeyValue structures.
+int key_value_compare_keys(const void *a, const void *b) {
+ return (int)((KeyValue*)a)->key - (int)((KeyValue*)b)->key;
+}
+
+// Search an array of key value pairs for the item with the specified value.
+KeyValue* find_item_by_value(const char * const value) {
+ unsigned int i;
+ for (i = 0; i < number_of_key_values; i++) {
+ if (strcmp(key_values[i].value, value) == 0) {
+ return &key_values[i];
+ }
+ }
+ return NULL;
+}
+
+// Sort an array of key value pairs by key.
+void sort_items_by_key() {
+ qsort(key_values, number_of_key_values, sizeof(*key_values),
+ key_value_compare_keys);
+}
diff --git a/cmockery_0_1_2/src/example/key_value_test.c b/cmockery_0_1_2/src/example/key_value_test.c
new file mode 100644
index 0000000..4f58e57
--- /dev/null
+++ b/cmockery_0_1_2/src/example/key_value_test.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <string.h>
+#include <cmockery.h>
+
+/* This is duplicated here from the module setup_teardown.c to reduce the
+ * number of files used in this test. */
+typedef struct KeyValue {
+ unsigned int key;
+ const char* value;
+} KeyValue;
+
+void set_key_values(KeyValue * const new_key_values,
+ const unsigned int new_number_of_key_values);
+extern KeyValue* find_item_by_value(const char * const value);
+extern void sort_items_by_key();
+
+static KeyValue key_values[] = {
+ { 10, "this" },
+ { 52, "test" },
+ { 20, "a" },
+ { 13, "is" },
+};
+
+void create_key_values(void **state) {
+ KeyValue * const items = (KeyValue*)test_malloc(sizeof(key_values));
+ memcpy(items, key_values, sizeof(key_values));
+ *state = (void*)items;
+ set_key_values(items, sizeof(key_values) / sizeof(key_values[0]));
+}
+
+void destroy_key_values(void **state) {
+ test_free(*state);
+ set_key_values(NULL, 0);
+}
+
+void test_find_item_by_value(void **state) {
+ unsigned int i;
+ for (i = 0; i < sizeof(key_values) / sizeof(key_values[0]); i++) {
+ KeyValue * const found = find_item_by_value(key_values[i].value);
+ assert_true(found);
+ assert_int_equal(found->key, key_values[i].key);
+ assert_string_equal(found->value, key_values[i].value);
+ }
+}
+
+void test_sort_items_by_key(void **state) {
+ unsigned int i;
+ KeyValue * const kv = *state;
+ sort_items_by_key();
+ for (i = 1; i < sizeof(key_values) / sizeof(key_values[0]); i++) {
+ assert_true(kv[i - 1].key < kv[i].key);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ const UnitTest tests[] = {
+ unit_test_setup_teardown(test_find_item_by_value, create_key_values,
+ destroy_key_values),
+ unit_test_setup_teardown(test_sort_items_by_key, create_key_values,
+ destroy_key_values),
+ };
+ return run_tests(tests);
+}
diff --git a/cmockery_0_1_2/src/example/product_database.c b/cmockery_0_1_2/src/example/product_database.c
new file mode 100644
index 0000000..6c6ecf2
--- /dev/null
+++ b/cmockery_0_1_2/src/example/product_database.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <database.h>
+
+// Connect to the database containing customer information.
+DatabaseConnection* connect_to_product_database() {
+ return connect_to_database("products.abcd.org", 322);
+}
+
diff --git a/cmockery_0_1_2/src/example/product_database_test.c b/cmockery_0_1_2/src/example/product_database_test.c
new file mode 100644
index 0000000..d3c5109
--- /dev/null
+++ b/cmockery_0_1_2/src/example/product_database_test.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmockery.h>
+#include <database.h>
+
+extern DatabaseConnection* connect_to_product_database();
+
+/* Mock connect to database function.
+ * NOTE: This mock function is very general could be shared between tests
+ * that use the imaginary database.h module. */
+DatabaseConnection* connect_to_database(const char * const url,
+ const unsigned int port) {
+ check_expected(url);
+ check_expected(port);
+ return (DatabaseConnection*)mock();
+}
+
+void test_connect_to_product_database(void **state) {
+ expect_string(connect_to_database, url, "products.abcd.org");
+ expect_value(connect_to_database, port, 322);
+ will_return(connect_to_database, 0xDA7ABA53);
+ assert_int_equal((int)connect_to_product_database(), 0xDA7ABA53);
+}
+
+/* This test will fail since the expected URL is different to the URL that is
+ * passed to connect_to_database() by connect_to_product_database(). */
+void test_connect_to_product_database_bad_url(void **state) {
+ expect_string(connect_to_database, url, "products.abcd.com");
+ expect_value(connect_to_database, port, 322);
+ will_return(connect_to_database, 0xDA7ABA53);
+ assert_int_equal((int)connect_to_product_database(), 0xDA7ABA53);
+}
+
+/* This test will fail since the mock connect_to_database() will attempt to
+ * retrieve a value for the parameter port which isn't specified by this
+ * test function. */
+void test_connect_to_product_database_missing_parameter(void **state) {
+ expect_string(connect_to_database, url, "products.abcd.org");
+ will_return(connect_to_database, 0xDA7ABA53);
+ assert_int_equal((int)connect_to_product_database(), 0xDA7ABA53);
+}
+
+int main(int argc, char* argv[]) {
+ const UnitTest tests[] = {
+ unit_test(test_connect_to_product_database),
+ unit_test(test_connect_to_product_database_bad_url),
+ unit_test(test_connect_to_product_database_missing_parameter),
+ };
+ return run_tests(tests);
+}
diff --git a/cmockery_0_1_2/src/example/run_tests.c b/cmockery_0_1_2/src/example/run_tests.c
new file mode 100644
index 0000000..f6d7620
--- /dev/null
+++ b/cmockery_0_1_2/src/example/run_tests.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmockery.h>
+
+// A test case that does nothing and succeeds.
+void null_test_success(void **state) {
+}
+
+int main(int argc, char* argv[]) {
+ const UnitTest tests[] = {
+ unit_test(null_test_success),
+ };
+ return run_tests(tests);
+}
diff --git a/cmockery_0_1_2/src/google/cmockery.h b/cmockery_0_1_2/src/google/cmockery.h
new file mode 100644
index 0000000..827d3c4
--- /dev/null
+++ b/cmockery_0_1_2/src/google/cmockery.h
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef CMOCKERY_H_
+#define CMOCKERY_H_
+/*
+ * These headers or their equivalents should be included prior to including
+ * this header file.
+ *
+ * #include <stdarg.h>
+ * #include <stddef.h>
+ * #include <setjmp.h>
+ *
+ * This allows test applications to use custom definitions of C standard
+ * library functions and types.
+ */
+
+// For those who are used to __func__ from gcc.
+#ifndef __func__
+#define __func__ __FUNCTION__
+#endif
+
+// Retrieves a return value for the current function.
+#define mock() _mock(__func__, __FILE__, __LINE__)
+
+/* Stores a value to be returned by the specified function later.
+ * The count parameter returns the number of times the value should be returned
+ * by mock(). If count is set to -1 the value will always be returned.
+ */
+#define will_return(function, value) \
+ _will_return(#function, __FILE__, __LINE__, (void*)value, 1)
+#define will_return_count(function, value, count) \
+ _will_return(#function, __FILE__, __LINE__, (void*)value, count)
+
+/* Add a custom parameter checking function. If the event parameter is NULL
+ * the event structure is allocated internally by this function. If event
+ * parameter is provided it must be allocated on the heap and doesn't need to
+ * be deallocated by the caller.
+ */
+#define expect_check(function, parameter, check_function, check_data) \
+ _expect_check(#function, #parameter, __FILE__, __LINE__, check_function, \
+ check_data)
+
+/* Add an event to check a parameter, using check_expected(), against a set of
+ * values. See will_return() for a description of the count parameter.
+ */
+#define expect_in_set(function, parameter, value_array) \
+ expect_in_set_count(function, parameter, value_array, 1)
+#define expect_in_set_count(function, parameter, value_array, count) \
+ _expect_in_set(#function, #parameter, __FILE__, __LINE__, value_array, \
+ sizeof(value_array) / sizeof(value_array[0]), count)
+#define expect_not_in_set(function, parameter, value_array) \
+ expect_not_in_set_count(function, parameter, value_array, 1)
+#define expect_not_in_set_count(function, parameter, value_array, count) \
+ _expect_not_in_set( \
+ #function, #parameter, __FILE__, __LINE__, value_array, \
+ sizeof(value_array) / sizeof(value_array[0]), count)
+
+
+/* Add an event to check a parameter, using check_expected(), against a
+ * signed range. Where range is minimum <= value <= maximum.
+ * See will_return() for a description of the count parameter.
+ */
+#define expect_in_range(function, parameter, minimum, maximum) \
+ expect_in_range_count(function, parameter, minimum, maximum, 1)
+#define expect_in_range_count(function, parameter, minimum, maximum, count) \
+ _expect_in_range(#function, #parameter, __FILE__, __LINE__, minimum, \
+ maximum, count)
+
+/* Add an event to check a parameter, using check_expected(), against a
+ * signed range. Where range is value < minimum or value > maximum.
+ * See will_return() for a description of the count parameter.
+ */
+#define expect_not_in_range(function, parameter, minimum, maximum) \
+ expect_not_in_range_count(function, parameter, minimum, maximum, 1)
+#define expect_not_in_range_count(function, parameter, minimum, maximum, \
+ count) \
+ _expect_not_in_range(#function, #parameter, __FILE__, __LINE__, \
+ minimum, maximum, count)
+
+/* Add an event to check whether a parameter, using check_expected(), is or
+ * isn't a value. See will_return() for a description of the count parameter.
+ */
+#define expect_value(function, parameter, value) \
+ expect_value_count(function, parameter, value, 1)
+#define expect_value_count(function, parameter, value, count) \
+ _expect_value(#function, #parameter, __FILE__, __LINE__, (void*)value, \
+ count)
+#define expect_not_value(function, parameter, value) \
+ expect_not_value_count(function, parameter, value, 1)
+#define expect_not_value_count(function, parameter, value, count) \
+ _expect_not_value(#function, #parameter, __FILE__, __LINE__, \
+ (void*)value, count)
+
+/* Add an event to check whether a parameter, using check_expected(),
+ * is or isn't a string. See will_return() for a description of the count
+ * parameter.
+ */
+#define expect_string(function, parameter, string) \
+ expect_string_count(function, parameter, string, 1)
+#define expect_string_count(function, parameter, string, count) \
+ _expect_string(#function, #parameter, __FILE__, __LINE__, (void*)string, \
+ count)
+#define expect_not_string(function, parameter, string) \
+ expect_not_string_count(function, parameter, string, 1)
+#define expect_not_string_count(function, parameter, string, count) \
+ _expect_not_string(#function, #parameter, __FILE__, __LINE__, \
+ (void*)string, count)
+
+/* Add an event to check whether a parameter, using check_expected() does or
+ * doesn't match an area of memory. See will_return() for a description of
+ * the count parameter.
+ */
+#define expect_memory(function, parameter, memory, size) \
+ expect_memory_count(function, parameter, memory, size, 1)
+#define expect_memory_count(function, parameter, memory, size, count) \
+ _expect_memory(#function, #parameter, __FILE__, __LINE__, (void*)memory, \
+ size, count)
+#define expect_not_memory(function, parameter, memory, size) \
+ expect_not_memory_count(function, parameter, memory, size, 1)
+#define expect_not_memory_count(function, parameter, memory, size, count) \
+ _expect_not_memory(#function, #parameter, __FILE__, __LINE__, \
+ (void*)memory, size, count)
+
+
+/* Add an event to allow any value for a parameter checked using
+ * check_expected(). See will_return() for a description of the count
+ * parameter.
+ */
+#define expect_any(function, parameter) \
+ expect_any_count(function, parameter, 1)
+#define expect_any_count(function, parameter, count) \
+ _expect_any(#function, #parameter, __FILE__, __LINE__, count)
+
+/* Determine whether a function parameter is correct. This ensures the next
+ * value queued by one of the expect_*() macros matches the specified variable.
+ */
+#define check_expected(parameter) \
+ _check_expected(__func__, #parameter, __FILE__, __LINE__, (void*)parameter)
+
+// Assert that the given expression is true.
+#define assert_true(c) _assert_true((int)(c), #c, __FILE__, __LINE__)
+// Assert that the given expression is false.
+#define assert_false(c) _assert_true(!((int)(c)), #c, __FILE__, __LINE__)
+
+// Assert that the two given integers are equal, otherwise fail.
+#define assert_int_equal(a, b) _assert_int_equal(a, b, __FILE__, __LINE__)
+// Assert that the two given integers are not equal, otherwise fail.
+#define assert_int_not_equal(a, b) \
+ _assert_int_not_equal(a, b, __FILE__, __LINE__)
+
+// Assert that the two given strings are equal, otherwise fail.
+#define assert_string_equal(a, b) \
+ _assert_string_equal((const char*)a, (const char*)b, __FILE__, __LINE__)
+// Assert that the two given strings are not equal, otherwise fail.
+#define assert_string_not_equal(a, b) \
+ _assert_string_not_equal((const char*)a, (const char*)b, __FILE__, \
+ __LINE__)
+
+// Assert that the two given areas of memory are equal, otherwise fail.
+#define assert_memory_equal(a, b, size) \
+ _assert_memory_equal((const char*)a, (const char*)b, size, __FILE__, \
+ __LINE__)
+// Assert that the two given areas of memory are not equal, otherwise fail.
+#define assert_memory_not_equal(a, b, size) \
+ _assert_memory_not_equal((const char*)a, (const char*)b, size, __FILE__, \
+ __LINE__)
+
+// Assert that the specified value is >= minimum and <= maximum.
+#define assert_in_range(value, minimum, maximum) \
+ _assert_in_range((int)value, (int)minimum, (int)maximum, __FILE__, \
+ __LINE__)
+// Assert that the specified value is < minumum or > maximum
+#define assert_not_in_range(value, minimum, maximum) \
+ _assert_not_in_range((int)value, (int)minimum, (int)maximum, __FILE__, \
+ __LINE__)
+
+// Assert that the specified value is within a set.
+#define assert_in_set(value, values, number_of_values) \
+ _assert_in_set(value, values, number_of_values, __FILE__, __LINE__)
+// Assert that the specified value is not within a set.
+#define assert_not_in_set(value, values, number_of_values) \
+ _assert_not_in_set(value, values, number_of_values, __FILE__, __LINE__)
+
+
+// Forces the test to fail immediately and quit.
+#define fail() _fail(__FILE__, __LINE__)
+
+// Generic method to kick off testing
+#define run_test(f) _run_test(#f, f, NULL, UNIT_TEST_FUNCTION_TYPE_TEST, NULL)
+
+// Initializes a UnitTest structure.
+#define unit_test(f) { #f, f, UNIT_TEST_FUNCTION_TYPE_TEST }
+#define unit_test_setup(test, setup) \
+ { #test "_" #setup, setup, UNIT_TEST_FUNCTION_TYPE_SETUP }
+#define unit_test_teardown(test, teardown) \
+ { #test "_" #teardown, teardown, UNIT_TEST_FUNCTION_TYPE_TEARDOWN }
+
+/* Initialize an array of UnitTest structures with a setup function for a test
+ * and a teardown function. Either setup or teardown can be NULL.
+ */
+#define unit_test_setup_teardown(test, setup, teardown) \
+ unit_test_setup(test, setup), \
+ unit_test(test), \
+ unit_test_teardown(test, teardown)
+
+/*
+ * Run tests specified by an array of UnitTest structures. The following
+ * example illustrates this macro's use with the unit_test macro.
+ *
+ * void Test0();
+ * void Test1();
+ *
+ * int main(int argc, char* argv[]) {
+ * const UnitTest tests[] = {
+ * unit_test(Test0);
+ * unit_test(Test1);
+ * };
+ * return run_tests(tests);
+ * }
+ */
+#define run_tests(tests) _run_tests(tests, sizeof(tests) / sizeof(tests)[0])
+
+// Dynamic allocators
+#define test_malloc(size) _test_malloc(size, __FILE__, __LINE__)
+#define test_calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
+#define test_free(ptr) _test_free(ptr, __FILE__, __LINE__)
+
+// Redirect malloc, calloc and free to the unit test allocators.
+#if UNIT_TESTING
+#define malloc test_malloc
+#define calloc test_calloc
+#define free test_free
+#endif // UNIT_TESTING
+
+/*
+ * Ensure mock_assert() is called. If mock_assert() is called the assert
+ * expression string is returned.
+ * For example:
+ *
+ * #define assert mock_assert
+ *
+ * void showmessage(const char *message) {
+ * assert(message);
+ * }
+ *
+ * int main(int argc, const char* argv[]) {
+ * expect_assert_failure(show_message(NULL));
+ * printf("succeeded\n");
+ * return 0;
+ * }
+ */
+#define expect_assert_failure(function_call) \
+ { \
+ const char* expression = (const char*)setjmp(global_expect_assert_env); \
+ global_expecting_assert = 1; \
+ if (expression) { \
+ print_message("Expected assertion %s occurred\n", expression); \
+ global_expecting_assert = 0; \
+ } else { \
+ function_call ; \
+ global_expecting_assert = 0; \
+ print_error("Expected assert in %s\n", #function_call); \
+ _fail(__FILE__, __LINE__); \
+ } \
+ }
+
+// Function prototype for setup, test and teardown functions.
+typedef void (*UnitTestFunction)(void **state);
+
+// Function that determines whether a function parameter value is correct.
+typedef int (*CheckParameterValue)(const void *value, void *check_value_data);
+
+// Type of the unit test function.
+typedef enum UnitTestFunctionType {
+ UNIT_TEST_FUNCTION_TYPE_TEST = 0,
+ UNIT_TEST_FUNCTION_TYPE_SETUP,
+ UNIT_TEST_FUNCTION_TYPE_TEARDOWN,
+} UnitTestFunctionType;
+
+/* Stores a unit test function with its name and type.
+ * NOTE: Every setup function must be paired with a teardown function. It's
+ * possible to specify NULL function pointers.
+ */
+typedef struct UnitTest {
+ const char* name;
+ UnitTestFunction function;
+ UnitTestFunctionType function_type;
+} UnitTest;
+
+
+// Location within some source code.
+typedef struct SourceLocation {
+ const char* file;
+ int line;
+} SourceLocation;
+
+// Event that's called to check a parameter value.
+typedef struct CheckParameterEvent {
+ SourceLocation location;
+ const char *parameter_name;
+ CheckParameterValue check_value;
+ void *check_value_data;
+} CheckParameterEvent;
+
+// Used by expect_assert_failure() and mock_assert().
+extern int global_expecting_assert;
+extern jmp_buf global_expect_assert_env;
+
+// Retrieves a value for the given function, as set by "will_return".
+void* _mock(const char * const function, const char* const file,
+ const int line);
+
+void _expect_check(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line,
+ const CheckParameterValue check_function, void * const check_data,
+ CheckParameterEvent * const event, const int count);
+
+void _expect_in_set(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void *values[],
+ const size_t number_of_values, const int count);
+void _expect_not_in_set(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void *values[],
+ const size_t number_of_values, const int count);
+
+void _expect_in_range(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line,
+ const int minimum, const int maximum, const int count);
+void _expect_not_in_range(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line,
+ const int minimum, const int maximum, const int count);
+void _expect_value(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void* const value,
+ const int count);
+void _expect_not_value(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const void* const value,
+ const int count);
+void _expect_string(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const char* string,
+ const int count);
+void _expect_not_string(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const char* string,
+ const int count);
+void _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);
+void _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);
+void _expect_any(
+ const char* const function, const char* const parameter,
+ const char* const file, const int line, const int count);
+
+void _check_expected(
+ const char * const function_name, const char * const parameter_name,
+ const char* file, const int line, const void* value);
+
+// Can be used to replace assert in tested code so that in conjuction with
+// check_assert() it's possible to determine whether an assert condition has
+// failed without stopping a test.
+void mock_assert(const int result, const char* const expression,
+ const char * const file, const int line);
+
+void _will_return(const char * const function_name, const char * const file,
+ const int line, const void* const value, const int count);
+void _assert_true(const int result, const char* const expression,
+ const char * const file, const int line);
+void _assert_int_equal(const int a, const int b, const char * const file,
+ const int line);
+void _assert_int_not_equal(const int a, const int b, const char * const file,
+ const int line);
+void _assert_string_equal(const char * const a, const char * const b,
+ const char * const file, const int line);
+void _assert_string_not_equal(const char * const a, const char * const b,
+ const char *file, const int line);
+void _assert_memory_equal(const void * const a, const void * const b,
+ const size_t size, const char* const file,
+ const int line);
+void _assert_memory_not_equal(const void * const a, const void * const b,
+ const size_t size, const char* const file,
+ const int line);
+void _assert_in_range(const int value, const int minimum, const int maximum,
+ const char* const file, const int line);
+void _assert_not_in_range(const int value, const int minimum,
+ const int maximum, const char* const file,
+ const int line);
+void _assert_in_set(const void * const value, const void *values[],
+ const size_t number_of_values, const char* const file,
+ const int line);
+void _assert_not_in_set(const void * const value, const void *values[],
+ const size_t number_of_values, const char* const file,
+ const int line);
+
+void* _test_malloc(const size_t size, const char* file, const int line);
+void* _test_calloc(const size_t number_of_elements, const size_t size,
+ const char* file, const int line);
+void _test_free(void* const ptr, const char* file, const int line);
+
+void _fail(const char * const file, const int line);
+int _run_test(
+ const char * const function_name, const UnitTestFunction Function,
+ void ** const state, const UnitTestFunctionType function_type,
+ const void* const heap_check_point);
+int _run_tests(const UnitTest * const tests, const size_t number_of_tests);
+
+// Standard output and error print methods.
+void print_message(const char* const format, ...);
+void print_error(const char* const format, ...);
+void vprint_message(const char* const format, va_list args);
+void vprint_error(const char* const format, va_list args);
+
+#endif // CMOCKERY_H_