#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include <time.h>
+#include <float.h>
+#include <errno.h>
+#include <limits.h>
/*
* This allows to add a platform specific header file. Some embedded platforms
#define MALLOC_ALLOC_PATTERN 0xBA
#define MALLOC_FREE_PATTERN 0xCD
/* Alignment of allocated blocks. NOTE: This must be base2. */
+#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGNMENT sizeof(size_t)
+#endif
/* Printf formatting for source code locations. */
#define SOURCE_LOCATION_FORMAT "%s:%u"
/*
- * Declare and initialize the pointer member of ValuePointer variable name
- * with ptr.
+ * Declare and initialize a LargestIntegralType variable name
+ * with value the conversion of ptr.
*/
#define declare_initialize_value_pointer_pointer(name, ptr) \
- ValuePointer name ; \
- name.value = 0; \
- name.x.pointer = (void*)(ptr)
-
-/*
- * Declare and initialize the value member of ValuePointer variable name
- * with val.
- */
-#define declare_initialize_value_pointer_value(name, val) \
- ValuePointer name ; \
- name.value = val
+ LargestIntegralType name ; \
+ name = (LargestIntegralType) (uintptr_t) ptr
-/* Cast a LargestIntegralType to pointer_type via a ValuePointer. */
+/* Cast a LargestIntegralType to pointer_type. */
#define cast_largest_integral_type_to_pointer( \
pointer_type, largest_integral_type) \
- ((pointer_type)((ValuePointer*)&(largest_integral_type))->x.pointer)
-
-/* Used to cast LargetIntegralType to void* and vice versa. */
-typedef union ValuePointer {
- LargestIntegralType value;
- struct {
-#if defined(WORDS_BIGENDIAN) && (WORDS_SIZEOF_VOID_P == 4)
- unsigned int padding;
-#endif
- void *pointer;
- } x;
-} ValuePointer;
+ ((pointer_type)(uintptr_t)(largest_integral_type))
/* Doubly linked list node. */
typedef struct ListNode {
static int cm_error_message_enabled = 1;
static CMOCKA_THREAD char *cm_error_message;
-void cm_print_error(const char * const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2);
-
/*
* Keeps track of the calling context returned by setenv() so that the fail()
* method can jump out of a test.
static const char *global_test_filter_pattern;
+static const char *global_skip_filter_pattern;
+
#ifndef _WIN32
/* Signals caught by exception_handler(). */
static const int exception_signals[] = {
cm_print_error(SOURCE_LOCATION_FORMAT ": Skipped!\n", file, line);
global_skip_test = 1;
exit_test(1);
+
+ /* Unreachable */
+ exit(-1);
}
/* Initialize a SourceLocation structure. */
{
char *p = NULL;
+ // Terminate if there is no valid data
+ if (src == NULL || src_len == 0 || pattern == NULL || repl == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
p = strstr(src, pattern);
+ /* There is nothing to replace */
if (p == NULL) {
- return -1;
+ return 0;
}
+ const size_t pattern_len = strlen(pattern);
+ const size_t repl_len = strlen(repl);
do {
- size_t of = p - src;
+ size_t offset = p - src;
size_t l = strlen(src);
- size_t pl = strlen(pattern);
- size_t rl = strlen(repl);
/* overflow check */
- if (src_len <= l + MAX(pl, rl) + 1) {
+ if (src_len <= l + MAX(pattern_len, repl_len) + 1) {
return -1;
}
- if (rl != pl) {
- memmove(src + of + rl, src + of + pl, l - of - pl + 1);
+ if (repl_len != pattern_len) {
+ memmove(src + offset + repl_len,
+ src + offset + pattern_len,
+ l - offset - pattern_len + 1);
}
- memcpy(src + of, repl, rl);
+ memcpy(src + offset, repl, repl_len);
if (str_replaced != NULL) {
*str_replaced = 1;
}
- p = strstr(src, pattern);
+ p = strstr(src + offset + repl_len, pattern);
} while (p != NULL);
return 0;
remove_always_return_values_from_list(&global_call_ordering_head);
if (check_for_leftover_values_list(&global_call_ordering_head,
- "%s function was expected to be called but was not not.\n")) {
+ "%s function was expected to be called but was not.\n")) {
error_occurred = 1;
}
if (error_occurred) {
SymbolMapValue * const map_value = (SymbolMapValue*)value;
const LargestIntegralType children = cast_ptr_to_largest_integral_type(cleanup_value_data);
assert_non_null(value);
- list_free(&map_value->symbol_values_list_head,
- children ? free_symbol_map_value : free_value,
- (void *) ((uintptr_t)children - 1));
+ if (children == 0) {
+ list_free(&map_value->symbol_values_list_head,
+ free_value,
+ NULL);
+ } else {
+ list_free(&map_value->symbol_values_list_head,
+ free_symbol_map_value,
+ (void *)((uintptr_t)children - 1));
+ }
+
free(map_value);
}
child_node = child_node->next, ++leftover_count) {
const FuncOrderingValue *const o =
(const FuncOrderingValue*) child_node->value;
- cm_print_error(error_message, o->function);
+ cm_print_error("%s: %s", error_message, o->function);
cm_print_error(SOURCE_LOCATION_FORMAT
": note: remaining item was declared here\n",
o->location.file, o->location.line);
if (!list_empty(child_list)) {
if (number_of_symbol_names == 1) {
const ListNode *child_node;
- cm_print_error(error_message, value->symbol_name);
+ cm_print_error("%s: %s", error_message, value->symbol_name);
for (child_node = child_list->next; child_node != child_list;
child_node = child_node->next) {
list_add_value(&global_call_ordering_head, ordering, count);
}
+/* Returns 1 if the specified float values are equal, else returns 0. */
+static int float_compare(const float left,
+ const float right,
+ const float epsilon) {
+ float absLeft;
+ float absRight;
+ float largest;
+ float relDiff;
+
+ float diff = left - right;
+ diff = (diff >= 0.f) ? diff : -diff;
+
+ // Check if the numbers are really close -- needed
+ // when comparing numbers near zero.
+ if (diff <= epsilon) {
+ return 1;
+ }
+
+ absLeft = (left >= 0.f) ? left : -left;
+ absRight = (right >= 0.f) ? right : -right;
+
+ largest = (absRight > absLeft) ? absRight : absLeft;
+ relDiff = largest * FLT_EPSILON;
+
+ if (diff > relDiff) {
+ return 0;
+ }
+ return 1;
+}
+
+/* Returns 1 if the specified float values are equal. If the values are not equal
+ * an error is displayed and 0 is returned. */
+static int float_values_equal_display_error(const float left,
+ const float right,
+ const float epsilon) {
+ const int equal = float_compare(left, right, epsilon);
+ if (!equal) {
+ cm_print_error(FloatPrintfFormat " != "
+ FloatPrintfFormat "\n", left, right);
+ }
+ return equal;
+}
+
+/* Returns 1 if the specified float values are different. If the values are equal
+ * an error is displayed and 0 is returned. */
+static int float_values_not_equal_display_error(const float left,
+ const float right,
+ const float epsilon) {
+ const int not_equal = (float_compare(left, right, epsilon) == 0);
+ if (!not_equal) {
+ cm_print_error(FloatPrintfFormat " == "
+ FloatPrintfFormat "\n", left, right);
+ }
+ return not_equal;
+}
+
+/* Returns 1 if the specified double values are equal, else returns 0. */
+static int double_compare(const double left,
+ const double right,
+ const double epsilon) {
+ double absLeft;
+ double absRight;
+ double largest;
+ double relDiff;
+
+ double diff = left - right;
+ diff = (diff >= 0.f) ? diff : -diff;
+
+ /*
+ * Check if the numbers are really close -- needed
+ * when comparing numbers near zero.
+ */
+ if (diff <= epsilon) {
+ return 1;
+ }
+
+ absLeft = (left >= 0.f) ? left : -left;
+ absRight = (right >= 0.f) ? right : -right;
+
+ largest = (absRight > absLeft) ? absRight : absLeft;
+ relDiff = largest * FLT_EPSILON;
+
+ if (diff > relDiff) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Returns 1 if the specified double values are equal. If the values are not
+ * equal an error is displayed and 0 is returned.
+ */
+static int double_values_equal_display_error(const double left,
+ const double right,
+ const double epsilon) {
+ const int equal = double_compare(left, right, epsilon);
+
+ if (!equal) {
+ cm_print_error(DoublePrintfFormat " != "
+ DoublePrintfFormat "\n", left, right);
+ }
+
+ return equal;
+}
+
+/*
+ * Returns 1 if the specified double values are different. If the values are
+ * equal an error is displayed and 0 is returned.
+ */
+static int double_values_not_equal_display_error(const double left,
+ const double right,
+ const double epsilon) {
+ const int not_equal = (double_compare(left, right, epsilon) == 0);
+
+ if (!not_equal) {
+ cm_print_error(DoublePrintfFormat " == "
+ DoublePrintfFormat "\n", left, right);
+ }
+
+ return not_equal;
+}
+
/* 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 LargestIntegralType left,
size_t differences = 0;
size_t i;
for (i = 0; i < size; i++) {
- const char l = a[i];
- const char r = b[i];
+ const unsigned char l = a[i];
+ const unsigned char r = b[i];
if (l != r) {
if (differences < 16) {
- cm_print_error("difference at offset %" PRIdS " 0x%02x 0x%02x\n",
+ cm_print_error("difference at offset %" PRIdS " 0x%02hhx 0x%02hhx\n",
i, l, r);
}
differences ++;
check_integer_set->size_of_set = number_of_values;
_expect_check(
function, parameter, file, line, check_function,
- check_data.value, &check_integer_set->event, count);
+ check_data, &check_integer_set->event, count);
}
check_integer_range->minimum = minimum;
check_integer_range->maximum = maximum;
_expect_check(function, parameter, file, line, check_function,
- check_data.value, &check_integer_range->event, count);
+ check_data, &check_integer_range->event, count);
}
declare_initialize_value_pointer_pointer(string_pointer,
discard_const(string));
_expect_check(function, parameter, file, line, check_string,
- string_pointer.value, NULL, count);
+ string_pointer, NULL, count);
}
declare_initialize_value_pointer_pointer(string_pointer,
discard_const(string));
_expect_check(function, parameter, file, line, check_not_string,
- string_pointer.value, NULL, count);
+ string_pointer, NULL, count);
}
/* CheckParameterValue callback to check whether a parameter equals an area of
check_data->memory = mem;
check_data->size = size;
_expect_check(function, parameter, file, line, check_function,
- check_data_pointer.value, &check_data->event, count);
+ check_data_pointer, &check_data->event, count);
}
}
}
+void _assert_float_equal(const float a,
+ const float b,
+ const float epsilon,
+ const char * const file,
+ const int line) {
+ if (!float_values_equal_display_error(a, b, epsilon)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_float_not_equal(const float a,
+ const float b,
+ const float epsilon,
+ const char * const file,
+ const int line) {
+ if (!float_values_not_equal_display_error(a, b, epsilon)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_double_equal(const double a,
+ const double b,
+ const double epsilon,
+ const char * const file,
+ const int line) {
+ if (!double_values_equal_display_error(a, b, epsilon)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_double_not_equal(const double a,
+ const double b,
+ const double epsilon,
+ const char * const file,
+ const int line) {
+ if (!double_values_not_equal_display_error(a, b, epsilon)) {
+ _fail(file, line);
+ }
+}
+
void _assert_int_equal(
const LargestIntegralType a, const LargestIntegralType b,
const char * const file, const int line) {
return &global_allocated_blocks;
}
-static void *libc_malloc(size_t size)
+static void *libc_calloc(size_t nmemb, size_t size)
{
-#undef malloc
- return malloc(size);
-#define malloc test_malloc
+#undef calloc
+ return calloc(nmemb, size);
+#define calloc test_calloc
}
static void libc_free(void *ptr)
if (cm_error_message == NULL) {
/* CREATE MESSAGE */
- cm_error_message = libc_malloc(len + 1);
+ cm_error_message = libc_calloc(1, len + 1);
if (cm_error_message == NULL) {
/* TODO */
goto end;
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);
+ void *ptr = NULL;
+
+ if (size > 0 && number_of_elements > SIZE_MAX / size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ptr = _test_malloc(number_of_elements * size, file, line);
if (ptr) {
memset(ptr, 0, number_of_elements * size);
}
return ptr;
}
+#define calloc test_calloc
/* Use the real free in this function. */
break;
}
exit_test(1);
+
+ /* Unreachable */
+ exit(-1);
}
#ifndef _WIN32
-static void exception_handler(int sig) {
+CMOCKA_NORETURN static void exception_handler(int sig) {
const char *sig_strerror = "";
#ifdef HAVE_STRSIGNAL
cm_print_error("Test failed with exception: %s(%d)",
sig_strerror, sig);
exit_test(1);
+
+ /* Unreachable */
+ exit(-1);
}
#else /* _WIN32 */
}
/* Standard output and error print methods. */
-void vprint_message(const char* const format, va_list args) {
- char buffer[1024];
+void vprint_message(const char* const format, va_list args)
+{
+ char buffer[4096];
+
vsnprintf(buffer, sizeof(buffer), format, args);
printf("%s", buffer);
fflush(stdout);
}
-void vprint_error(const char* const format, va_list args) {
- char buffer[1024];
+void vprint_error(const char* const format, va_list args)
+{
+ char buffer[4096];
+
vsnprintf(buffer, sizeof(buffer), format, args);
fprintf(stderr, "%s", buffer);
fflush(stderr);
static int xml_printed;
static int file_append;
+static void cmprepare_xml_attribute_string(char *buf, size_t buf_len, const char *src)
+{
+ snprintf(buf, buf_len, "%s", src);
+ c_strreplace(buf, buf_len, "&", "&", NULL);
+ c_strreplace(buf, buf_len, "\"", """, NULL);
+ c_strreplace(buf, buf_len, "\'", "'", NULL);
+ c_strreplace(buf, buf_len, "<", "<", NULL);
+ c_strreplace(buf, buf_len, ">", ">", NULL);
+}
+
static void cmprintf_group_finish_xml(const char *group_name,
size_t total_executed,
size_t total_failed,
}
}
+ char group_name_escaped[1024];
+ cmprepare_xml_attribute_string(group_name_escaped,
+ sizeof(group_name_escaped),
+ group_name);
+
fprintf(fp, "<testsuites>\n");
fprintf(fp, " <testsuite name=\"%s\" time=\"%.3f\" "
"tests=\"%u\" failures=\"%u\" errors=\"%u\" skipped=\"%u\" >\n",
- group_name,
+ group_name_escaped,
total_runtime, /* seconds */
(unsigned)total_executed,
(unsigned)total_failed,
for (i = 0; i < total_executed; i++) {
struct CMUnitTestState *cmtest = &cm_tests[i];
+ /* Escape double quotes and remove spaces in test name */
+ char test_name_escaped[1024];
+ cmprepare_xml_attribute_string(test_name_escaped,
+ sizeof(test_name_escaped),
+ cmtest->test->name);
+
fprintf(fp, " <testcase name=\"%s\" time=\"%.3f\" >\n",
- cmtest->test->name, cmtest->runtime);
+ test_name_escaped, cmtest->runtime);
switch (cmtest->status) {
case CM_TEST_ERROR:
}
}
-static void cmprintf_group_start_standard(const size_t num_tests)
+static void cmprintf_group_start_standard(const char *group_name,
+ const size_t num_tests)
{
- print_message("[==========] Running %u test(s).\n",
- (unsigned)num_tests);
+ print_message("[==========] %s: Running %zu test(s).\n",
+ group_name,
+ num_tests);
}
-static void cmprintf_group_finish_standard(size_t total_executed,
+static void cmprintf_group_finish_standard(const char *group_name,
+ size_t total_executed,
size_t total_passed,
size_t total_failed,
size_t total_errors,
{
size_t i;
- print_message("[==========] %u test(s) run.\n", (unsigned)total_executed);
+ print_message("[==========] %s: %zu test(s) run.\n",
+ group_name,
+ total_executed);
print_error("[ PASSED ] %u test(s).\n",
(unsigned)(total_passed));
if (total_skipped) {
- print_error("[ SKIPPED ] %"PRIdS " test(s), listed below:\n", total_skipped);
+ print_error("[ SKIPPED ] %s: %zu test(s), listed below:\n",
+ group_name,
+ total_skipped);
for (i = 0; i < total_executed; i++) {
struct CMUnitTestState *cmtest = &cm_tests[i];
print_error("[ SKIPPED ] %s\n", cmtest->test->name);
}
}
- print_error("\n %u SKIPPED TEST(S)\n", (unsigned)(total_skipped));
+ print_error("\n %zu SKIPPED TEST(S)\n", total_skipped);
}
if (total_failed) {
- print_error("[ FAILED ] %"PRIdS " test(s), listed below:\n", total_failed);
+ print_error("[ FAILED ] %s: %zu test(s), listed below:\n",
+ group_name,
+ total_failed);
for (i = 0; i < total_executed; i++) {
struct CMUnitTestState *cmtest = &cm_tests[i];
print_error("[ FAILED ] %s\n", cmtest->test->name);
}
}
- print_error("\n %u FAILED TEST(S)\n",
- (unsigned)(total_failed + total_errors));
+ print_error("\n %zu FAILED TEST(S)\n",
+ (total_failed + total_errors));
}
}
static void cmprintf_group_start_tap(const size_t num_tests)
{
+ static bool version_printed = false;
+ if (!version_printed) {
+ print_message("TAP version 13\n");
+ version_printed = true;
+ }
+
print_message("1..%u\n", (unsigned)num_tests);
}
}
static void cmprintf_tap(enum cm_printf_type type,
- uint32_t test_number,
+ size_t test_number,
const char *test_name,
const char *error_message)
{
}
break;
case PRINTF_TEST_SKIPPED:
- print_message("not ok %u # SKIP %s\n", (unsigned)test_number, test_name);
+ print_message("ok %u # SKIP %s\n", (unsigned)test_number, test_name);
break;
case PRINTF_TEST_ERROR:
print_message("not ok %u - %s %s\n",
}
}
-static void cmprintf_group_start(const size_t num_tests)
+static void cmprintf_group_start(const char *group_name,
+ const size_t num_tests)
{
enum cm_message_output output;
switch (output) {
case CM_OUTPUT_STDOUT:
- cmprintf_group_start_standard(num_tests);
+ cmprintf_group_start_standard(group_name, num_tests);
break;
case CM_OUTPUT_SUBUNIT:
break;
switch (output) {
case CM_OUTPUT_STDOUT:
- cmprintf_group_finish_standard(total_executed,
- total_passed,
- total_failed,
- total_errors,
- total_skipped,
- cm_tests);
+ cmprintf_group_finish_standard(group_name,
+ total_executed,
+ total_passed,
+ total_failed,
+ total_errors,
+ total_skipped,
+ cm_tests);
break;
case CM_OUTPUT_SUBUNIT:
break;
case CM_OUTPUT_TAP:
- cmprintf_group_finish_tap(group_name, total_executed, total_passed, total_skipped);
+ cmprintf_group_finish_tap(group_name,
+ total_executed,
+ total_passed,
+ total_skipped);
break;
case CM_OUTPUT_XML:
cmprintf_group_finish_xml(group_name,
global_test_filter_pattern = pattern;
}
+void cmocka_set_skip_filter(const char *pattern)
+{
+ global_skip_filter_pattern = pattern;
+}
+
/****************************************************************************
* TIME CALCULATIONS
****************************************************************************/
diff = cm_tspecdiff(clock1, clock0);
- ret = diff.tv_sec;
+ ret = (double) diff.tv_sec;
ret += (double) diff.tv_nsec / (double) 1E9;
return ret;
/* Make sure LargestIntegralType is at least the size of a pointer. */
assert_true(sizeof(LargestIntegralType) >= sizeof(void*));
- cm_tests = (struct CMUnitTestState *)libc_malloc(sizeof(struct CMUnitTestState) * num_tests);
+ cm_tests = libc_calloc(1, sizeof(struct CMUnitTestState) * num_tests);
if (cm_tests == NULL) {
return -1;
}
|| tests[i].setup_func != NULL
|| tests[i].teardown_func != NULL)) {
if (global_test_filter_pattern != NULL) {
- int ok;
+ int match;
+
+ match = c_strmatch(tests[i].name, global_test_filter_pattern);
+ if (!match) {
+ continue;
+ }
+ }
+ if (global_skip_filter_pattern != NULL) {
+ int match;
- ok = c_strmatch(tests[i].name, global_test_filter_pattern);
- if (!ok) {
+ match = c_strmatch(tests[i].name, global_skip_filter_pattern);
+ if (match) {
continue;
}
}
}
}
- cmprintf_group_start(total_tests);
+ cmprintf_group_start(group_name, total_tests);
rc = 0;
libc_free(cm_tests);
fail_if_blocks_allocated(group_check_point, "cmocka_group_tests");
- return total_failed + total_errors;
+ return (int)(total_failed + total_errors);
}
/****************************************************************************
int _run_group_tests(const UnitTest * const tests, const size_t number_of_tests)
{
UnitTestFunction setup = NULL;
- const char *setup_name;
+ const char *setup_name = NULL;
size_t num_setups = 0;
UnitTestFunction teardown = NULL;
const char *teardown_name = NULL;
/*
* Copyright 2008 Google Inc.
- * Copyright 2014-2018 Andreas Schneider <asn@cryptomilk.org>
+ * Copyright 2014-2022 Andreas Schneider <asn@cryptomilk.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @defgroup cmocka The CMocka API
*
- * These headers or their equivalents should be included prior to including
+ * These headers or their equivalents MUST be included prior to including
* this header file.
* @code
* #include <stdarg.h>
+ * #include <stdbool.h>
* #include <stddef.h>
+ * #include <stdint.h>
* #include <setjmp.h>
* @endcode
*
# endif /* _WIN32 */
#endif /* LargestIntegralTypePrintfFormat */
+#ifndef FloatPrintfFormat
+# define FloatPrintfFormat "%f"
+#endif /* FloatPrintfFormat */
+
+#ifndef DoublePrintfFormat
+# define DoublePrintfFormat "%f"
+#endif /* DoublePrintfFormat */
+
/* Perform an unsigned cast to LargestIntegralType. */
#define cast_to_largest_integral_type(value) \
((LargestIntegralType)(value))
/* Smallest integral type capable of holding a pointer. */
-#if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED)
+#if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) && !defined(HAVE_UINTPTR_T) && !defined(__UINTPTR_TYPE__)
# if defined(_WIN32)
/* WIN32 is an ILP32 platform */
typedef unsigned int uintptr_t;
# elif defined(_WIN64)
- typedef unsigned long int uintptr_t
+ typedef unsigned long int uintptr_t;
# else /* _WIN32 */
/* ILP32 and LP64 platforms */
#define CMOCKA_DEPRECATED
#endif
+#if defined(__GNUC__)
+#define CMOCKA_NORETURN __attribute__ ((noreturn))
+#elif defined(_MSC_VER)
+#define CMOCKA_NORETURN __declspec(noreturn)
+#else
+#define CMOCKA_NORETURN
+#endif
+
#define WILL_RETURN_ALWAYS -1
#define WILL_RETURN_ONCE -2
* @defgroup cmocka_mock Mock Objects
* @ingroup cmocka
*
- * Mock objects mock objects are simulated objects that mimic the behavior of
+ * Mock objects are simulated objects that mimic the behavior of
* real objects. Instead of calling the real objects, the tested object calls a
* mock object that merely asserts that the correct methods were called, with
* the expected parameters, in the correct order.
* }
* @endcode
*
- * For a complete example please at a look
- * <a href="http://git.cryptomilk.org/projects/cmocka.git/tree/example/chef_wrap/waiter_test_wrap.c">here</a>.
+ * For a complete example please take a look
+ * <a href="https://git.cryptomilk.org/projects/cmocka.git/tree/example/mock">here</a>.
*
* @{
*/
* }
* @endcode
*
- * For a complete example please at a look at
- * <a href="http://git.cryptomilk.org/projects/cmocka.git/tree/example/chef_wrap/waiter_test_wrap.c">here</a>
+ * For a complete example please take a look
+ * <a href="https://git.cryptomilk.org/projects/cmocka.git/tree/example/mock">here</a>
*
* @{
*/
#ifdef DOXYGEN
/**
- * @brief Add an event to check if a parameter is the given value.
+ * @brief Add an event to check if a parameter is the given integer based value.
*
* The event is triggered by calling check_expected() in the mocked function.
*
*
* @param[in] value The value to check.
*
- * @see check_expected().
+ * @see check_expected()
+ * @see expect_string()
+ * @see expect_memory()
+ * @see expect_any()
*/
void expect_value(#function, #parameter, LargestIntegralType value);
#else
#ifdef DOXYGEN
/**
- * @brief Add an event to repeatedly check if a parameter is the given value.
+ * @brief Add an event to repeatedly check if a parameter is the given integer
+ * based value.
*
* The event is triggered by calling check_expected() in the mocked function.
*
* to -1 the value will always be returned.
*
* @see check_expected().
+ * @see expect_not_string()
+ * @see expect_not_memory()
*/
void expect_value_count(#function, #parameter, LargestIntegralType value, size_t count);
#else
expect_any_count(function, parameter, 1)
#endif
+#ifdef DOXYGEN
+/**
+ * @brief Add an event to always check if a parameter (of any value) has been passed.
+ *
+ * The event is triggered by calling check_expected() in the mocked function.
+ *
+ * @param[in] #function The function to add the check for.
+ *
+ * @param[in] #parameter The name of the parameter passed to the function.
+ *
+ * @see check_expected().
+ */
+void expect_any_always(#function, #parameter);
+#else
+#define expect_any_always(function, parameter) \
+ expect_any_count(function, parameter, WILL_RETURN_ALWAYS)
+#endif
+
#ifdef DOXYGEN
/**
* @brief Add an event to repeatedly check if a parameter (of any value) has
__FILE__, __LINE__)
#endif
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the two given float are equal given an epsilon.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if the float are not equal (given an epsilon).
+ *
+ * @param[in] a The first float to compare.
+ *
+ * @param[in] b The float to compare against the first one.
+ *
+ * @param[in] epsilon The epsilon used as margin for float comparison.
+ */
+void assert_float_equal(float a, float b, float epsilon);
+#else
+#define assert_float_equal(a, b, epsilon) \
+ _assert_float_equal((float)a, \
+ (float)b, \
+ (float)epsilon, \
+ __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the two given float are not equal given an epsilon.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if the float are not equal (given an epsilon).
+ *
+ * @param[in] a The first float to compare.
+ *
+ * @param[in] b The float to compare against the first one.
+ *
+ * @param[in] epsilon The epsilon used as margin for float comparison.
+ */
+void assert_float_not_equal(float a, float b, float epsilon);
+#else
+#define assert_float_not_equal(a, b, epsilon) \
+ _assert_float_not_equal((float)a, \
+ (float)b, \
+ (float)epsilon, \
+ __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the two given double are equal given an epsilon.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if the double are not equal (given an epsilon).
+ *
+ * @param[in] a The first double to compare.
+ *
+ * @param[in] b The double to compare against the first one.
+ *
+ * @param[in] epsilon The epsilon used as margin for double comparison.
+ */
+void assert_double_equal(double a, double b, double epsilon);
+#else
+#define assert_double_equal(a, b, epsilon) \
+ _assert_double_equal((double)a, \
+ (double)b, \
+ (double)epsilon, \
+ __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the two given double are not equal given an epsilon.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if the double are not equal (given an epsilon).
+ *
+ * @param[in] a The first double to compare.
+ *
+ * @param[in] b The double to compare against the first one.
+ *
+ * @param[in] epsilon The epsilon used as margin for double comparison.
+ */
+void assert_double_not_equal(double a, double b, double epsilon);
+#else
+#define assert_double_not_equal(a, b, epsilon) \
+ _assert_double_not_equal((float)a, \
+ (double)b, \
+ (double)epsilon, \
+ __FILE__, __LINE__)
+#endif
+
+
#ifdef DOXYGEN
/**
* @brief Assert that the two given strings are equal.
void assert_string_equal(const char *a, const char *b);
#else
#define assert_string_equal(a, b) \
- _assert_string_equal((const char*)(a), (const char*)(b), __FILE__, \
- __LINE__)
+ _assert_string_equal((a), (b), __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
void assert_string_not_equal(const char *a, const char *b);
#else
#define assert_string_not_equal(a, b) \
- _assert_string_not_equal((const char*)(a), (const char*)(b), __FILE__, \
- __LINE__)
+ _assert_string_not_equal((a), (b), __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
* created (e.g. expect_function_call()) than consumed with function_called().
* There are provisions such as ignore_function_calls() which allow this
* restriction to be circumvented in tests where mock calls for the code under
- * test are not the focus of the test.
+ * test are not the focus of the test. function_called() must be called from
+ * the same thread as expect_function_call(), and that thread must have been
+ * initialized for use by cmocka (see also the [Threading section of the main
+ * documentation page](index.html#main-threads)).
*
* The following example illustrates how a unit test instructs cmocka
* to expect a function_called() from a particular mock,
void fail_msg(const char *msg, ...);
#else
#define fail_msg(msg, ...) do { \
- print_error("ERROR: " msg "\n", ##__VA_ARGS__); \
+ cm_print_error("ERROR: " msg "\n", ##__VA_ARGS__); \
fail(); \
} while (0)
#endif
* @code
* static int setup(void **state) {
* int *answer = malloc(sizeof(int));
- * if (*answer == NULL) {
+ * if (answer == NULL) {
* return -1;
* }
* *answer = 42;
* @code
* static int setup(void **state) {
* int *answer = malloc(sizeof(int));
- * if (*answer == NULL) {
+ * if (answer == NULL) {
* return -1;
* }
* *answer = 42;
const char * const expression,
const char * const file,
const int line);
+void _assert_float_equal(const float a, const float n,
+ const float epsilon, const char* const file,
+ const int line);
+void _assert_float_not_equal(const float a, const float n,
+ const float epsilon, const char* const file,
+ const int line);
+void _assert_double_equal(const double a, const double n,
+ const double epsilon, const char* const file,
+ const int line);
+void _assert_double_not_equal(const double a, const double n,
+ const double epsilon, const char* const file,
+ const int line);
void _assert_int_equal(
const LargestIntegralType a, const LargestIntegralType b,
const char * const file, const int line);
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);
+CMOCKA_NORETURN void _fail(const char * const file, const int line);
-void _skip(const char * const file, const int line);
+CMOCKA_NORETURN void _skip(const char * const file, const int line);
int _run_test(
const char * const function_name, const UnitTestFunction Function,
void print_error(const char* const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2);
void vprint_message(const char* const format, va_list args) CMOCKA_PRINTF_ATTRIBUTE(1, 0);
void vprint_error(const char* const format, va_list args) CMOCKA_PRINTF_ATTRIBUTE(1, 0);
+void cm_print_error(const char* const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2);
enum cm_message_output {
CM_OUTPUT_STDOUT,
/**
* @brief Set a pattern to only run the test matching the pattern.
*
- * This allows to filter tests and only run the ones matching the pattern. Thep
+ * This allows to filter tests and only run the ones matching the pattern. The
* pattern can include two wildards. The first is '*', a wildcard that matches
* zero or more characters, or ‘?’, a wildcard that matches exactly one
* character.
*/
void cmocka_set_test_filter(const char *pattern);
+/**
+ * @brief Set a pattern to skip tests matching the pattern.
+ *
+ * This allows to filter tests and skip the ones matching the pattern. The
+ * pattern can include two wildards. The first is '*', a wildcard that matches
+ * zero or more characters, or ‘?’, a wildcard that matches exactly one
+ * character.
+ *
+ * @param[in] pattern The pattern to match, e.g. "test_wurst*"
+ */
+void cmocka_set_skip_filter(const char *pattern);
+
/** @} */
#endif /* CMOCKA_H_ */