diff options
Diffstat (limited to 'pw_unit_test/public/pw_unit_test/internal/framework.h')
-rw-r--r-- | pw_unit_test/public/pw_unit_test/internal/framework.h | 179 |
1 files changed, 179 insertions, 0 deletions
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..be93c64f8 100644 --- a/pw_unit_test/public/pw_unit_test/internal/framework.h +++ b/pw_unit_test/public/pw_unit_test/internal/framework.h @@ -52,26 +52,163 @@ #define FRIEND_TEST(test_suite_name, test_name) \ friend class test_suite_name##_##test_name##_Test +/// @def EXPECT_TRUE +/// Verifies that @p expr evaluates to true. +/// @param expr Condition to evaluate #define EXPECT_TRUE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, true)) + +/// @def EXPECT_FALSE +/// Verifies that @p expr evaluates to false. +/// @param expr Condition to evaluate #define EXPECT_FALSE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, false)) + +/// @def EXPECT_EQ +/// Verifies that @p lhs == @p rhs +/// <p> +/// Does pointer equality on pointers. If used on two C strings, it tests if +/// they are in the same memory location, not if they have the same value. Use +/// #EXPECT_STREQ to compare C strings (e.g. <code>const char*</code>) by value. +/// <p> +/// When comparing a pointer to <code>NULL</code> use +/// <code>EXPECT_EQ(ptr, nullptr)</code> instead of +/// <code>EXPECT_EQ(ptr, NULL)</code>. +/// @param lhs The left side of the equality comparison +/// @param rhs The right side of the equality comparison #define EXPECT_EQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, ==)) + +/// @def EXPECT_NE +/// Verifies that @p lhs != @p rhs +/// <p> +/// Does pointer equality on pointers. If used on two C strings, it tests if +/// they are in different memory locations, not if they have different values. +/// Use #EXPECT_STRNE to compare C strings (e.g. <code>const char*</code>) by +/// value. +/// <p> +/// When comparing a pointer to <code>NULL</code>, use +/// <code>EXPECT_NE(ptr, nullptr)</code> instead of +/// <code>EXPECT_NE(ptr, NULL)</code>. +/// @param lhs The left side of the inequality comparison +/// @param rhs The right side of the inequality comparison #define EXPECT_NE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, !=)) + +/// @def EXPECT_GT +/// Verifies that @p lhs > @p rhs +/// @param lhs The left side of the comparison +/// @param rhs The right side of the comparison #define EXPECT_GT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >)) + +/// @def EXPECT_GE +/// Verifies that @p lhs >= @p rhs +/// @param lhs The left side of the comparison +/// @param rhs The right side of the comparison #define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=)) + +/// @def EXPECT_LT +/// Verifies that @p lhs < @p rhs +/// @param lhs The left side of the comparison +/// @param rhs The right side of the comparison #define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <)) + +/// @def EXPECT_LE +/// Verifies that @p lhs <= @p rhs +/// @param lhs The left side of the comparison +/// @param rhs The right side of the comparison #define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=)) + +/// @def EXPECT_NEAR +/// Verifies that the difference between @p lhs and @p rhs does not exceed the +/// absolute error bound @p epsilon. +/// @param lhs The left side of the comparison +/// @param rhs The right side of the comparison +/// @param epsilon The maximum difference between @p lhs and @p rhs +#define EXPECT_NEAR(lhs, rhs, epsilon) \ + _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon)) + +/// @def EXPECT_FLOAT_EQ +/// Verifies that the two float values @p rhs and @p lhs are approximately +/// equal, to within 4 ULPs from each other. +/// @param lhs The left side of the equality comparison +/// @param rhs The right side of the equality comparison +#define EXPECT_FLOAT_EQ(lhs, rhs) \ + _PW_TEST_EXPECT( \ + _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon())) + +/// @def EXPECT_DOUBLE_EQ +/// Verifies that the two double values @p rhs and @p lhs are approximately +/// equal, to within 4 ULPs from each other. +/// @param lhs The left side of the equality comparison +/// @param rhs The right side of the equality comparison +#define EXPECT_DOUBLE_EQ(lhs, rhs) \ + _PW_TEST_EXPECT( \ + _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon())) + +/// @def EXPECT_STREQ +/// Verifies that the two C strings @p lhs and @p rhs have the same contents. +/// @param lhs The left side of the equality comparison +/// @param rhs The right side of the equality comparison #define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==)) + +/// @def EXPECT_STRNE +/// Verifies that the two C strings @p lhs and @p rhs have different content +/// @param lhs The left side of the inequality comparison +/// @param rhs The right side of the inequality comparison #define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=)) +/// @def ASSERT_TRUE +/// @see EXPECT_TRUE #define ASSERT_TRUE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, true)) + +/// @def ASSERT_FALSE +/// @see EXPECT_FALSE #define ASSERT_FALSE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, false)) + +/// @def ASSERT_EQ +/// @see EXPECT_EQ #define ASSERT_EQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, ==)) + +/// @def ASSERT_NE +/// @see EXPECT_NE #define ASSERT_NE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, !=)) + +/// @def ASSERT_GT +/// @see EXPECT_GT #define ASSERT_GT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >)) + +/// @def ASSERT_GE +/// @see EXPECT_GE #define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=)) + +/// @def ASSERT_LT +/// @see EXPECT_LT #define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <)) + +/// @def ASSERT_LE +/// @see EXPECT_LE #define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=)) + +/// @def ASSERT_NEAR +/// @see EXPECT_NEAR +#define ASSERT_NEAR(lhs, rhs, epsilon) \ + _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon)) + +/// @def ASSERT_FLOAT_EQ +/// @see EXPECT_FLOAT_EQ +#define ASSERT_FLOAT_EQ(lhs, rhs) \ + _PW_TEST_ASSERT( \ + _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon())) + +/// @def ASSERT_DOUBLE_EQ +/// @see EXPECT_DOUBLE_EQ +#define ASSERT_DOUBLE_EQ(lhs, rhs) \ + _PW_TEST_ASSERT( \ + _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon())) + +/// @def ASSERT_STREQ +/// @see EXPECT_STREQ #define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==)) + +/// @def ASSERT_STRNE +/// @see EXPECT_STRNE #define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=)) // Generates a non-fatal failure with a generic message. @@ -309,6 +446,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 +793,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) { \ |