diff options
-rw-r--r-- | include/cmocka.h | 54 | ||||
-rw-r--r-- | src/cmocka.c | 87 | ||||
-rw-r--r-- | src/cmocka.def | 2 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/test_double_macros.c | 40 |
5 files changed, 184 insertions, 0 deletions
diff --git a/include/cmocka.h b/include/cmocka.h index 9b47ceb..f282c06 100644 --- a/include/cmocka.h +++ b/include/cmocka.h @@ -111,6 +111,10 @@ typedef uintmax_t LargestIntegralType; # 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)) @@ -1282,6 +1286,50 @@ void 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 /** @@ -2273,6 +2321,12 @@ void _assert_float_equal(const float a, const float n, 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); diff --git a/src/cmocka.c b/src/cmocka.c index 76a9b93..6a31f77 100644 --- a/src/cmocka.c +++ b/src/cmocka.c @@ -1183,6 +1183,73 @@ static int float_values_not_equal_display_error(const float left, 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, @@ -1795,6 +1862,26 @@ void _assert_float_not_equal(const float a, } } +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) { diff --git a/src/cmocka.def b/src/cmocka.def index 3633dc1..1c2c653 100644 --- a/src/cmocka.def +++ b/src/cmocka.def @@ -1,5 +1,7 @@ LIBRARY cmocka EXPORTS + _assert_double_equal + _assert_double_not_equal _assert_float_equal _assert_float_not_equal _assert_in_range diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index def90d3..7487a9c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,6 +16,7 @@ set(CMOCKA_TESTS test_group_fixtures test_groups test_float_macros + test_double_macros test_assert_macros test_assert_macros_fail test_basics diff --git a/tests/test_double_macros.c b/tests/test_double_macros.c new file mode 100644 index 0000000..138c579 --- /dev/null +++ b/tests/test_double_macros.c @@ -0,0 +1,40 @@ +/* + * Copyright 2019 Arnaud Gelas <arnaud.gelas@sensefly.com> + * + * 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. + */ + +/* Use the unit test allocators */ +#define UNIT_TESTING 1 + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> + +/* A test case that does check if double is equal. */ +static void double_test_success(void **state) +{ + (void)state; /* unused */ + + assert_double_equal(0.5, 1. / 2., 0.000001); + assert_double_not_equal(0.5, 0.499, 0.000001); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(double_test_success), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} |