aboutsummaryrefslogtreecommitdiff
path: root/pw_unit_test
diff options
context:
space:
mode:
authorYuval Peress <peress@google.com>2023-11-08 20:16:40 +0000
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-11-08 20:16:40 +0000
commit996a3479d45a601d8a9aa68f7acf282800226191 (patch)
treeaab6e10ab4a5b724187fcce2e6565f10d91d852d /pw_unit_test
parent74ed509bc15e65bc898284b697cacde6684c8288 (diff)
downloadpigweed-996a3479d45a601d8a9aa68f7acf282800226191.tar.gz
pw_unit_test: Support *_NEAR, *_FLOAT_EQ, *_DOUBLE_EQ
Add implementation of the _NEAR checks using existing infrastructure. The same method is used for comparing floats and double. Error messaging was shortened compared to gTest's to save on buffer space. Change-Id: I8b5d490d48f756c61a6b7008e221c522f747fcae Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/179770 Reviewed-by: Alexei Frolov <frolv@google.com> Commit-Queue: Yuval Peress <peress@google.com>
Diffstat (limited to 'pw_unit_test')
-rw-r--r--pw_unit_test/framework_test.cc40
-rw-r--r--pw_unit_test/public/pw_unit_test/internal/framework.h58
2 files changed, 98 insertions, 0 deletions
diff --git a/pw_unit_test/framework_test.cc b/pw_unit_test/framework_test.cc
index 2e1fe90c4..211c665ce 100644
--- a/pw_unit_test/framework_test.cc
+++ b/pw_unit_test/framework_test.cc
@@ -57,6 +57,46 @@ TEST(PigweedTest, ExpectBasicComparisons) {
ASSERT_LE(-2, -2);
}
+TEST(PigweedTest, ExpectNearComparisons) {
+ EXPECT_NEAR(1, 2, 1);
+ ASSERT_NEAR(1, 2, 1);
+
+ EXPECT_NEAR(-5, 5, 10);
+ ASSERT_NEAR(-5, 5, 10);
+
+ int x = 17;
+ int epsilon = 5;
+
+ EXPECT_NEAR(x, 15, epsilon);
+ ASSERT_NEAR(x, 15, epsilon);
+}
+
+TEST(PigweedTest, ExpectFloatComparisons) {
+ EXPECT_FLOAT_EQ(5.0f, 10.0f / 2);
+ ASSERT_FLOAT_EQ(5.0f, 10.0f / 2);
+
+ EXPECT_FLOAT_EQ(-0.5f, -5.0f / 10);
+ ASSERT_FLOAT_EQ(-0.5f, -5.0f / 10);
+
+ float x = 17.0f / 20.0f;
+
+ EXPECT_FLOAT_EQ(x, 17.0f / 20.0f);
+ ASSERT_FLOAT_EQ(x, 17.0f / 20.0f);
+}
+
+TEST(PigweedTest, ExpectDoubleComparisons) {
+ EXPECT_DOUBLE_EQ(5.0, 10.0 / 2);
+ ASSERT_DOUBLE_EQ(5.0, 10.0 / 2);
+
+ EXPECT_DOUBLE_EQ(-0.5, -5.0 / 10);
+ ASSERT_DOUBLE_EQ(-0.5, -5.0 / 10);
+
+ double x = 17.0 / 20.0;
+
+ EXPECT_DOUBLE_EQ(x, 17.0 / 20.0);
+ ASSERT_DOUBLE_EQ(x, 17.0 / 20.0);
+}
+
TEST(PigweedTest, ExpectStringEquality) {
EXPECT_STREQ("", "");
EXPECT_STREQ("Yes", "Yes");
diff --git a/pw_unit_test/public/pw_unit_test/internal/framework.h b/pw_unit_test/public/pw_unit_test/internal/framework.h
index fce2293d1..78a59337d 100644
--- a/pw_unit_test/public/pw_unit_test/internal/framework.h
+++ b/pw_unit_test/public/pw_unit_test/internal/framework.h
@@ -60,6 +60,14 @@
#define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=))
#define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <))
#define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=))
+#define EXPECT_NEAR(lhs, rhs, epsilon) \
+ _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon))
+#define EXPECT_FLOAT_EQ(lhs, rhs) \
+ _PW_TEST_EXPECT( \
+ _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
+#define EXPECT_DOUBLE_EQ(lhs, rhs) \
+ _PW_TEST_EXPECT( \
+ _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
#define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==))
#define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=))
@@ -71,6 +79,14 @@
#define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=))
#define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <))
#define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=))
+#define ASSERT_NEAR(lhs, rhs, epsilon) \
+ _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon))
+#define ASSERT_FLOAT_EQ(lhs, rhs) \
+ _PW_TEST_ASSERT( \
+ _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
+#define ASSERT_DOUBLE_EQ(lhs, rhs) \
+ _PW_TEST_ASSERT( \
+ _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
#define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==))
#define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=))
@@ -309,6 +325,37 @@ class Framework {
framework.EndCurrentTest();
}
+ template <typename Expectation, typename Lhs, typename Rhs, typename Epsilon>
+ bool CurrentTestExpect(Expectation expectation,
+ const Lhs& lhs,
+ const Rhs& rhs,
+ const Epsilon& epsilon,
+ const char* expression,
+ int line) {
+ // Size of the buffer into which to write the string with the evaluated
+ // version of the arguments. This buffer is allocated on the unit test's
+ // stack, so it shouldn't be too large.
+ // TODO(hepler): Make this configurable.
+ [[maybe_unused]] constexpr size_t kExpectationBufferSizeBytes = 192;
+
+ const bool success = expectation(lhs, rhs, epsilon);
+ CurrentTestExpectSimple(
+ expression,
+#if PW_CXX_STANDARD_IS_SUPPORTED(17)
+ MakeString<kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
+ " within ",
+ ConvertForPrint(epsilon),
+ " of ",
+ ConvertForPrint(rhs))
+ .c_str(),
+#else
+ "(evaluation requires C++17)",
+#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
+ line,
+ success);
+ return success;
+ }
+
// Runs an expectation function for the currently active test case.
template <typename Expectation, typename Lhs, typename Rhs>
bool CurrentTestExpect(Expectation expectation,
@@ -625,6 +672,17 @@ inline void SetTestSuitesToRun(span<std::string_view> test_suites) {
#lhs " " #op " " #rhs, \
__LINE__)
+#define _PW_TEST_NEAR(lhs, rhs, epsilon) \
+ ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
+ [](const auto& _pw_lhs, const auto& _pw_rhs, const auto& _pw_epsilon) { \
+ return std::abs(_pw_lhs - _pw_rhs) <= _pw_epsilon; \
+ }, \
+ (lhs), \
+ (rhs), \
+ (epsilon), \
+ #lhs " within " #epsilon " of " #rhs, \
+ __LINE__)
+
#define _PW_TEST_C_STR(lhs, rhs, op) \
::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
[](const auto& _pw_lhs, const auto& _pw_rhs) { \