diff options
author | Joseph Ates <joseph.ates@msasafety.com> | 2016-02-10 12:16:13 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2016-02-10 13:18:11 +0100 |
commit | f8bba4b3a519147de59a2a7c3dc6262549e7e2bb (patch) | |
tree | 646f92fcc8b778916a6b380e06ab7bef2cb857da | |
parent | c971d6e5c26549c421d7fc4cc2965cea4c628866 (diff) | |
download | cmocka-f8bba4b3a519147de59a2a7c3dc6262549e7e2bb.tar.gz cmocka-f8bba4b3a519147de59a2a7c3dc6262549e7e2bb.tar.bz2 cmocka-f8bba4b3a519147de59a2a7c3dc6262549e7e2bb.zip |
cmocka: Add will_return_maybe() for ignoring mock returns
As both parameter and function call order checking allow for ignoring
cases where they are never invoked, the mock return values are at
somewhat of a mismatch in that they must always be returned at least
once (even in the case of will_return_always()). Therefore, the ability
to set the count to -2 on will_return_count was added with a new macro
(will_return_maybe) that indicates that that the value field may never
be returned and still allow a successful test.
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
-rw-r--r-- | include/cmocka.h | 35 | ||||
-rw-r--r-- | src/cmocka.c | 6 | ||||
-rw-r--r-- | test_ordering_fail.c | 95 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 14 | ||||
-rw-r--r-- | tests/test_returns.c | 69 | ||||
-rw-r--r-- | tests/test_returns_fail.c | 77 |
6 files changed, 289 insertions, 7 deletions
diff --git a/include/cmocka.h b/include/cmocka.h index 6242ff2..fecd873 100644 --- a/include/cmocka.h +++ b/include/cmocka.h @@ -304,9 +304,11 @@ void will_return(#function, LargestIntegralType value); * * @param[in] value The value to be returned by mock(). * - * @param[in] count The 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. + * @param[in] count The parameter indicates the number of times the value should + * be returned by mock(). If count is set to -1, the value + * will always be returned but must be returned at least once. + * If count is set to -2, the value will always be returned + * by mock(), but is not required to be returned. * * @see mock() */ @@ -339,6 +341,33 @@ void will_return_always(#function, LargestIntegralType value); will_return_count(function, (value), -1) #endif +#ifdef DOXYGEN +/** + * @brief Store a value that may be always returned by mock(). + * + * This stores a value which will always be returned by mock() but is not + * required to be returned by at least one call to mock(). Therefore, + * in contrast to will_return_always() which causes a test failure if it + * is not returned at least once, will_return_maybe() will never cause a test + * to fail if its value is not returned. + * + * @param[in] #function The function which should return the given value. + * + * @param[in] #value The value to be returned by mock(). + * + * This is equivalent to: + * @code + * will_return_count(function, value, -2); + * @endcode + * + * @see will_return_count() + * @see mock() + */ +void will_return_maybe(#function, LargestIntegralType value); +#else +#define will_return_maybe(function, value) \ + will_return_count(function, (value), -2) +#endif /** @} */ /** diff --git a/src/cmocka.c b/src/cmocka.c index 4f13f21..376acba 100644 --- a/src/cmocka.c +++ b/src/cmocka.c @@ -689,8 +689,10 @@ static int get_symbol_value( assert_true(return_value); *output = (void*) value_node->value; return_value = value_node->refcount; - if (--value_node->refcount == 0) { + if (value_node->refcount - 1 == 0) { list_remove_free(value_node, NULL, NULL); + } else if (value_node->refcount > -2) { + --value_node->refcount; } } else { return_value = get_symbol_value( @@ -943,7 +945,7 @@ void _will_return(const char * const function_name, const char * const file, const int count) { SymbolValue * const return_value = (SymbolValue*)malloc(sizeof(*return_value)); - assert_true(count > 0 || count == -1); + 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, diff --git a/test_ordering_fail.c b/test_ordering_fail.c new file mode 100644 index 0000000..652f5ad --- /dev/null +++ b/test_ordering_fail.c @@ -0,0 +1,95 @@ +#include "config.h" + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <cmocka_private.h> + +static void mock_test_a_called(void) +{ + function_called(); +} + +static void mock_test_b_called(void) +{ + function_called(); +} + +static void mock_test_c_called(void) +{ + function_called(); +} + +static void test_does_fail_for_unexpected_call(void **state) +{ + (void)state; + expect_function_call(mock_test_a_called); + expect_function_call(mock_test_a_called); + + mock_test_a_called(); + mock_test_a_called(); + mock_test_a_called(); +} + +static void test_does_fail_for_unmade_expected_call(void **state) +{ + (void)state; + expect_function_call(mock_test_a_called); + expect_function_call(mock_test_a_called); + + mock_test_a_called(); +} + +static void test_ordering_fails_out_of_order(void **state) +{ + (void)state; + expect_function_call(mock_test_a_called); + expect_function_call(mock_test_b_called); + expect_function_call(mock_test_a_called); + + mock_test_b_called(); +} + +static void test_ordering_fails_out_of_order_for_at_least_once_calls(void **state) +{ + (void)state; + expect_function_call_any(mock_test_a_called); + ignore_function_calls(mock_test_b_called); + + mock_test_b_called(); + mock_test_c_called(); +} + +/* Primarily used to test error message */ +static void test_fails_out_of_order_if_no_calls_found_on_any(void **state) +{ + (void)state; + expect_function_call_any(mock_test_a_called); + ignore_function_calls(mock_test_b_called); + + mock_test_a_called(); + mock_test_c_called(); +} + +static void test_fails_if_zero_count_used(void **state) +{ + (void)state; + expect_function_calls(mock_test_a_called, 0); + + mock_test_a_called(); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_does_fail_for_unexpected_call) + ,cmocka_unit_test(test_does_fail_for_unmade_expected_call) + ,cmocka_unit_test(test_does_fail_for_unmade_expected_call) + ,cmocka_unit_test(test_ordering_fails_out_of_order) + ,cmocka_unit_test(test_ordering_fails_out_of_order_for_at_least_once_calls) + ,cmocka_unit_test(test_fails_out_of_order_if_no_calls_found_on_any) + ,cmocka_unit_test(test_fails_if_zero_count_used) + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4b015ba..0422487 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,7 +19,9 @@ set(CMOCKA_TESTS test_skip test_setup_fail test_ordering - test_ordering_fail) + test_ordering_fail + test_returns + test_returns_fail) foreach(_CMOCKA_TEST ${CMOCKA_TESTS}) add_cmocka_test(${_CMOCKA_TEST} ${_CMOCKA_TEST}.c ${CMOCKA_STATIC_LIBRARY}) @@ -33,7 +35,7 @@ add_cmocka_test(test_cmockery test_cmockery.c ${CMOCKA_STATIC_LIBRARY}) ### Exceptions -# test_assert_macros_fail +# test_skip set_tests_properties( test_skip PROPERTIES @@ -57,6 +59,14 @@ set_tests_properties( "\\[ FAILED \\] 7 test" ) +# test_returns_fail ensure proper failures +set_tests_properties( + test_returns_fail + PROPERTIES + PASS_REGULAR_EXPRESSION + "\\[ FAILED \\] 3 test" +) + # test_exception_handler if (WIN32) set_tests_properties( diff --git a/tests/test_returns.c b/tests/test_returns.c new file mode 100644 index 0000000..b9370c9 --- /dev/null +++ b/tests/test_returns.c @@ -0,0 +1,69 @@ +#include "config.h" + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <cmocka_private.h> + +#include <stdlib.h> + +int mock_function(void); +void mock_function_call_times(size_t times, int expectedValue); + +int mock_function(void) +{ + return (int) mock(); +} + +void mock_function_call_times(size_t times, int expectedValue) +{ + size_t i; + for (i = 0u; i < times; ++i) + { + assert_int_equal(expectedValue, mock_function()); + } +} + +static void test_will_return_maybe_for_no_calls(void **state) +{ + (void) state; + + will_return_maybe(mock_function, 32); +} + +static void test_will_return_maybe_for_one_mock_call(void **state) +{ + int value; + + (void) state; + + value = rand(); + will_return_maybe(mock_function, value); + mock_function_call_times(1u, value); +} + +static void test_will_return_maybe_for_more_than_one_call(void **state) +{ + int value; + size_t numberOfCalls; + (void)state; + + value = rand(); + numberOfCalls = (size_t) ((rand()) % 20 + 2); + will_return_maybe(mock_function, value); + mock_function_call_times(numberOfCalls, value); +} + +int main(int argc, char **argv) { + const struct CMUnitTest alloc_tests[] = { + cmocka_unit_test(test_will_return_maybe_for_no_calls) + ,cmocka_unit_test(test_will_return_maybe_for_one_mock_call) + ,cmocka_unit_test(test_will_return_maybe_for_more_than_one_call) + }; + + (void)argc; + (void)argv; + + return cmocka_run_group_tests(alloc_tests, NULL, NULL); +} diff --git a/tests/test_returns_fail.c b/tests/test_returns_fail.c new file mode 100644 index 0000000..81197d3 --- /dev/null +++ b/tests/test_returns_fail.c @@ -0,0 +1,77 @@ +#include "config.h" + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <cmocka_private.h> + +#include <stdlib.h> + +int mock_function(void); +void mock_function_call_times(size_t times, int expectedValue); + +int mock_function(void) +{ + return (int) mock(); +} + +void mock_function_call_times(size_t times, int expectedValue) +{ + size_t i; + for (i = 0u; i < times; ++i) + { + assert_int_equal(expectedValue, mock_function()); + } +} + +static void test_will_return_fails_for_no_calls(void **state) +{ + (void) state; + + will_return(mock_function, 32); +} + +static void test_will_return_count_fails_for_unreturned_items(void **state) +{ + int value; + size_t numberOfCalls; + + (void) state; + + value = rand(); + numberOfCalls = (size_t) ((rand()) % 20 + 2); + + will_return_count(mock_function, value, numberOfCalls); + mock_function_call_times(numberOfCalls - 1u, value); +} + +static void test_will_return_always_fails_for_no_calls(void **state) +{ + int value; + + (void) state; + + value = rand(); + + will_return_always(mock_function, value); +} + +static int teardown(void **state) { + free(*state); + + return 0; +} + +int main(int argc, char **argv) { + const struct CMUnitTest alloc_tests[] = { + cmocka_unit_test_teardown(test_will_return_fails_for_no_calls, teardown) + ,cmocka_unit_test_teardown(test_will_return_count_fails_for_unreturned_items, teardown) + ,cmocka_unit_test_teardown(test_will_return_always_fails_for_no_calls, teardown) + }; + + (void)argc; + (void)argv; + + return cmocka_run_group_tests(alloc_tests, NULL, NULL); +} |