diff options
author | Yuval Peress <peress@google.com> | 2023-11-08 20:16:40 +0000 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-11-08 20:16:40 +0000 |
commit | 996a3479d45a601d8a9aa68f7acf282800226191 (patch) | |
tree | aab6e10ab4a5b724187fcce2e6565f10d91d852d /pw_unit_test | |
parent | 74ed509bc15e65bc898284b697cacde6684c8288 (diff) | |
download | pigweed-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.cc | 40 | ||||
-rw-r--r-- | pw_unit_test/public/pw_unit_test/internal/framework.h | 58 |
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) { \ |