summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Gelas <arnaud.gelas@sensefly.com>2019-02-04 15:52:30 +0100
committerAndreas Schneider <asn@cryptomilk.org>2019-11-19 15:38:34 +0100
commit226a89cc434649ca4a4230cccac81976dfda9592 (patch)
tree42bf9e0e620a9abafeb2e93d49e3451626884f21
parent1e21400a7923a2e539c7a4b078fb3e445a493c35 (diff)
downloadcmocka-226a89cc434649ca4a4230cccac81976dfda9592.tar.gz
cmocka-226a89cc434649ca4a4230cccac81976dfda9592.tar.xz
cmocka-226a89cc434649ca4a4230cccac81976dfda9592.zip
cmocka: Add new assert macros to compare 2 double given an epsilon.
assert_double_equal and assert_double_not_equal Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
-rw-r--r--include/cmocka.h54
-rw-r--r--src/cmocka.c87
-rw-r--r--src/cmocka.def2
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/test_double_macros.c40
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);
+}