aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Gelas <arnaud.gelas@sensefly.com>2019-01-15 17:33:14 +0100
committerAndreas Schneider <asn@cryptomilk.org>2019-01-22 13:24:26 +0100
commit10f50a294f876b6419bd1e297f2a84913736a35c (patch)
tree725fc1ef60bfa30edcba36e3abe63e93ebc64624
parentbd0667c6d99019843b4893393f2ab4d3e6b43468 (diff)
downloadcmocka-10f50a294f876b6419bd1e297f2a84913736a35c.tar.gz
cmocka-10f50a294f876b6419bd1e297f2a84913736a35c.tar.xz
cmocka-10f50a294f876b6419bd1e297f2a84913736a35c.zip
include: Add new assert macros to compare 2 floats given an epsilon.
assert_float_equal and assert_float_not_equal
-rw-r--r--include/cmocka.h55
-rw-r--r--src/cmocka.c77
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/test_float_macros.c37
4 files changed, 170 insertions, 0 deletions
diff --git a/include/cmocka.h b/include/cmocka.h
index 377c696..e7a3783 100644
--- a/include/cmocka.h
+++ b/include/cmocka.h
@@ -106,6 +106,10 @@ typedef uintmax_t LargestIntegralType;
# endif /* _WIN32 */
#endif /* LargestIntegralTypePrintfFormat */
+#ifndef FloatPrintfFormat
+# define FloatPrintfFormat "%f"
+#endif /* FloatPrintfFormat */
+
/* Perform an unsigned cast to LargestIntegralType. */
#define cast_to_largest_integral_type(value) \
((LargestIntegralType)(value))
@@ -1235,6 +1239,51 @@ void assert_int_not_equal(int a, int b);
#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 strings are equal.
*
* The function prints an error message to standard error and terminates the
@@ -2217,6 +2266,12 @@ void _assert_return_code(const LargestIntegralType result,
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_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 4ae65b7..ff79161 100644
--- a/src/cmocka.c
+++ b/src/cmocka.c
@@ -43,6 +43,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <float.h>
/*
* This allows to add a platform specific header file. Some embedded platforms
@@ -1122,6 +1123,62 @@ void _expect_function_call(
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 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,
@@ -1714,6 +1771,26 @@ void _assert_return_code(const LargestIntegralType result,
}
}
+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_int_equal(
const LargestIntegralType a, const LargestIntegralType b,
const char * const file, const int line) {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f7ea00b..1e93940 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -15,6 +15,7 @@ set(CMOCKA_TESTS
test_fixtures
test_group_fixtures
test_groups
+ test_float_macros
test_assert_macros
test_assert_macros_fail
test_basics
diff --git a/tests/test_float_macros.c b/tests/test_float_macros.c
new file mode 100644
index 0000000..38dcb6d
--- /dev/null
+++ b/tests/test_float_macros.c
@@ -0,0 +1,37 @@
+/*
+ * 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 float is equal. */
+static void float_test_success(void **state) {
+ assert_float_equal(0.5f, 1.f / 2.f, 0.000001f);
+ assert_float_not_equal(0.5, 0.499f, 0.000001f);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(float_test_success),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}