20#if defined(GTEST_TEST)
22 "GTEST_TEST is already defined. Make sure googletest headers are not " \
23 "included when using the pw_unit_test light backend."
31#include "pw_bytes/alignment.h"
32#include "pw_polyfill/standard.h"
33#include "pw_preprocessor/compiler.h"
34#include "pw_preprocessor/util.h"
35#include "pw_span/span.h"
36#include "pw_unit_test/config.h"
37#include "pw_unit_test/event_handler.h"
39#if PW_CXX_STANDARD_IS_SUPPORTED(17)
47#define GTEST_TEST(test_suite_name, test_name) \
48 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(void , test_suite_name); \
49 _PW_TEST(test_suite_name, test_name, ::pw::unit_test::internal::Test)
60#if !(defined(GTEST_DONT_DEFINE_TEST) && GTEST_DONT_DEFINE_TEST)
61#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
69#define TEST_F(test_fixture, test_name) \
70 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(int , test_fixture); \
71 _PW_TEST(test_fixture, test_name, test_fixture)
82#define FRIEND_TEST(test_suite_name, test_name) \
83 friend class test_suite_name##_##test_name##_Test
89#define EXPECT_TRUE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, true))
95#define EXPECT_FALSE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, false))
110#define EXPECT_EQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, ==))
124#define EXPECT_NE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, !=))
131#define EXPECT_GT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >))
138#define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=))
145#define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <))
152#define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=))
161#define EXPECT_NEAR(lhs, rhs, epsilon) \
162 _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon))
170#define EXPECT_FLOAT_EQ(lhs, rhs) \
172 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
180#define EXPECT_DOUBLE_EQ(lhs, rhs) \
182 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
189#define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==))
196#define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=))
200#define ASSERT_TRUE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, true))
204#define ASSERT_FALSE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, false))
208#define ASSERT_EQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, ==))
212#define ASSERT_NE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, !=))
216#define ASSERT_GT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >))
220#define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=))
224#define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <))
228#define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=))
232#define ASSERT_NEAR(lhs, rhs, epsilon) \
233 _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon))
237#define ASSERT_FLOAT_EQ(lhs, rhs) \
239 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
243#define ASSERT_DOUBLE_EQ(lhs, rhs) \
245 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
249#define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==))
253#define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=))
257#define ADD_FAILURE() \
258 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
259 "(line is not executed)", "(line was executed)", __LINE__, false); \
265#define GTEST_FAIL() return ADD_FAILURE()
270#define GTEST_SKIP() \
271 ::pw::unit_test::internal::Framework::Get().CurrentTestSkip(__LINE__); \
272 return _PW_UNIT_TEST_LOG
279#if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
280#define FAIL() GTEST_FAIL()
286#define GTEST_SUCCEED() \
287 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
288 "(success)", "(success)", __LINE__, true); \
297#if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
298#define SUCCEED() GTEST_SUCCEED()
309#define RUN_ALL_TESTS() \
310 ::pw::unit_test::internal::Framework::Get().RunAllTests()
314#define GTEST_HAS_DEATH_TEST 0
318#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
320 static_cast<void>(statement); \
321 static_cast<void>(regex); \
323 static_assert(true, "Macros must be terminated with a semicolon")
327#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
328 EXPECT_DEATH_IF_SUPPORTED(statement, regex)
332#if PW_CXX_STANDARD_IS_SUPPORTED(17)
354StatusWithSize UnknownTypeToString(
const T& value, span<char> buffer) {
355 StringBuilder sb(buffer);
356 sb <<
'<' <<
sizeof(value) <<
"-byte object at 0x" << &value;
365 constexpr size_t kPrintMaybeUnintializedBytes = 0;
367 constexpr size_t kBytesToPrint =
368 std::min(
sizeof(value), kPrintMaybeUnintializedBytes);
370 if (kBytesToPrint != 0u) {
374 const std::byte* bytes =
reinterpret_cast<const std::byte*
>(&value);
376 for (
size_t i = 0; i < kBytesToPrint; ++i) {
377 sb <<
' ' << bytes[i];
381 if (
sizeof(value) == kBytesToPrint + 1) {
382 sb <<
' ' << bytes[
sizeof(value) - 1];
383 }
else if (
sizeof(value) > kBytesToPrint) {
389 return sb.status_with_size();
403using SetUpTestSuiteFunc = void (*)();
404using TearDownTestSuiteFunc = void (*)();
409 const char*
const c_str;
412constexpr size_t MaxPaddingNeededToRaiseAlignment(
size_t current_align,
414 if (new_align < current_align) {
417 return new_align - current_align;
426 : current_test_(
nullptr),
427 current_result_(TestResult::kSuccess),
428 run_tests_summary_{.passed_tests = 0,
431 .disabled_tests = 0},
433 event_handler_(
nullptr),
436 static Framework& Get() {
return framework_; }
440 void RegisterTest(
TestInfo* test)
const;
444 inline void RegisterEventHandler(
EventHandler* event_handler) {
445 event_handler_ = event_handler;
453#if PW_CXX_STANDARD_IS_SUPPORTED(17)
457 void SetTestSuitesToRun(span<std::string_view> test_suites) {
458 test_suites_to_run_ = test_suites;
462 bool ShouldRunTest(
const TestInfo& test_info)
const;
465 bool IsSkipped()
const {
return current_result_ == TestResult::kSkipped; }
468 bool HasFailure()
const {
return current_result_ == TestResult::kFailure; }
478 template <
typename TestInstance>
479 static void CreateAndRunTest(
const TestInfo& test_info) {
481 sizeof(TestInstance) +
482 MaxPaddingNeededToRaiseAlignment(
483 alignof(
decltype(memory_pool_)),
alignof(TestInstance)) <=
484 sizeof(memory_pool_),
485 "The test memory pool is too small for this test. Either increase "
486 "PW_UNIT_TEST_CONFIG_MEMORY_POOL_SIZE or decrease the size of your "
490 framework.StartTest(test_info);
494 std::memset(&framework.memory_pool_, 0xa5,
sizeof(framework.memory_pool_));
496 framework.SetUpTestSuiteIfNeeded(TestInstance::SetUpTestSuite);
501 AlignUp(&framework.memory_pool_,
alignof(TestInstance));
502 TestInstance* test_instance =
new (aligned_pool) TestInstance();
503 test_instance->PigweedTestRun();
507 test_instance->~TestInstance();
509 framework.TearDownTestSuiteIfNeeded(TestInstance::TearDownTestSuite);
511 framework.EndCurrentTest();
514 template <
typename Expectation,
typename Lhs,
typename Rhs,
typename Epsilon>
515 bool CurrentTestExpect(Expectation expectation,
518 const Epsilon& epsilon,
519 const char* expression,
525 [[maybe_unused]]
constexpr size_t kExpectationBufferSizeBytes = 192;
527 const bool success = expectation(lhs, rhs, epsilon);
528 CurrentTestExpectSimple(
530#
if PW_CXX_STANDARD_IS_SUPPORTED(17)
531 MakeString<kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
533 ConvertForPrint(epsilon),
535 ConvertForPrint(rhs))
538 "(evaluation requires C++17)",
546 template <
typename Expectation,
typename Lhs,
typename Rhs>
547 bool CurrentTestExpect(Expectation expectation,
550 [[maybe_unused]]
const char* expectation_string,
551 const char* expression,
557 [[maybe_unused]]
constexpr size_t kExpectationBufferSizeBytes = 192;
559 const bool success = expectation(lhs, rhs);
560 CurrentTestExpectSimple(
562#
if PW_CXX_STANDARD_IS_SUPPORTED(17)
563 MakeString<kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
567 ConvertForPrint(rhs))
570 "(evaluation requires C++17)",
578 void CurrentTestSkip(
int line);
581 void CurrentTestExpectSimple(
const char* expression,
582 const char* evaluated_expression,
590 static constexpr const void* ConvertForPrint(
const char* str) {
return str; }
592 static constexpr const void* ConvertForPrint(
char* str) {
return str; }
594 static constexpr const char* ConvertForPrint(
CStringArg value) {
598 template <
typename T>
599 static constexpr T ConvertForPrint(T&& value) {
600 return std::forward<T>(value);
604 void SetUpTestSuiteIfNeeded(SetUpTestSuiteFunc set_up_ts)
const;
607 void TearDownTestSuiteIfNeeded(TearDownTestSuiteFunc tear_down_ts)
const;
610 void StartTest(
const TestInfo& test);
613 void EndCurrentTest();
626 TestResult current_result_;
637#if PW_CXX_STANDARD_IS_SUPPORTED(17)
638 span<std::string_view> test_suites_to_run_;
640 span<const char*> test_suites_to_run_;
643 alignas(std::max_align_t) std::byte memory_pool_[config::kMemoryPoolSize];
651 TestInfo(
const char*
const test_suite_name,
652 const char*
const test_name,
653 const char*
const file_name,
656 .suite_name = test_suite_name,
657 .test_name = test_name,
658 .file_name = file_name,
660 Framework::Get().RegisterTest(
this);
665 const TestCase& test_case()
const {
return test_case_; }
667 bool enabled()
const;
669 void run()
const { run_(*
this); }
671 TestInfo* next()
const {
return next_; }
672 void set_next(
TestInfo* next) { next_ = next; }
702 Test& operator=(
const Test&) =
delete;
704 virtual ~Test() =
default;
706 static void SetUpTestSuite() {}
707 static void TearDownTestSuite() {}
709 static bool HasFailure() {
return Framework::Get().HasFailure(); }
712 void PigweedTestRun() {
715 if (!Framework::Get().IsSkipped()) {
729 virtual void SetUp() {}
732 virtual void TearDown() {}
738 virtual void PigweedTestBody() = 0;
742constexpr bool HasNoUnderscores(
const char* suite) {
743 const char* disabled_prefix =
"DISABLED_";
745 for (; *suite !=
'\0'; ++suite) {
746 if (*suite == *disabled_prefix) {
747 disabled_prefix += 1;
749 disabled_prefix =
"";
765 template <
typename T>
766 constexpr const IgnoreLogs& operator<<(
const T&)
const {
780 constexpr void operator=(
const IgnoreLogs&)
const {}
783#define _PW_UNIT_TEST_LOG \
784 ::pw::unit_test::internal::ReturnHelper() = \
785 ::pw::unit_test::internal::IgnoreLogs()
789#if PW_CXX_STANDARD_IS_SUPPORTED(17)
790inline void SetTestSuitesToRun(span<std::string_view> test_suites) {
791 internal::Framework::Get().SetTestSuitesToRun(test_suites);
798#define _PW_TEST(test_suite_name, test_name, parent_class) \
799 static_assert(sizeof(#test_suite_name) > 1, \
800 "The test suite name must not be empty"); \
801 static_assert(::pw::unit_test::internal::HasNoUnderscores(#test_suite_name), \
802 "The test suite name (" #test_suite_name \
803 ") cannot contain underscores"); \
804 static_assert(sizeof(#test_name) > 1, "The test name must not be empty"); \
806 _PW_TEST_CLASS(test_suite_name, \
808 test_suite_name##_##test_name##_Test, \
811#define _PW_TEST_CLASS(suite, name, class_name, parent_class) \
812 class class_name final : public parent_class { \
814 void PigweedTestBody() override; \
822 PW_NO_SANITIZE("address") \
826 ::pw::unit_test::internal::TestInfo _pw_unit_test_Info_##suite##_##name( \
830 ::pw::unit_test::internal::Framework::CreateAndRunTest<class_name>); \
834 void class_name::PigweedTestBody()
836#define _PW_TEST_ASSERT(expectation) \
837 if (!(expectation)) \
838 return _PW_UNIT_TEST_LOG
840#define _PW_TEST_EXPECT(expectation) \
841 if (!(expectation)) \
844#define _PW_TEST_BOOL(expr, value) \
845 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
846 [](bool lhs, bool rhs) { return lhs == rhs; }, \
847 static_cast<bool>(expr), \
850 #expr " is " #value, \
853#define _PW_TEST_OP(lhs, rhs, op) \
854 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
855 [](const auto& _pw_lhs, const auto& _pw_rhs) { \
856 return _pw_lhs op _pw_rhs; \
861 #lhs " " #op " " #rhs, \
864#define _PW_TEST_NEAR(lhs, rhs, epsilon) \
865 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
866 [](const auto& _pw_lhs, const auto& _pw_rhs, const auto& _pw_epsilon) { \
867 return std::abs(_pw_lhs - _pw_rhs) <= _pw_epsilon; \
872 #lhs " within " #epsilon " of " #rhs, \
875#define _PW_TEST_C_STR(lhs, rhs, op) \
876 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
877 [](const auto& _pw_lhs, const auto& _pw_rhs) { \
878 auto cmp = [](const char* l, const char* r) -> int { \
882 return std::strcmp(l, r); \
884 return cmp(_pw_lhs.c_str, _pw_rhs.c_str) op 0; \
886 ::pw::unit_test::internal::CStringArg{lhs}, \
887 ::pw::unit_test::internal::CStringArg{rhs}, \
889 #lhs " " #op " " #rhs, \
900#if !defined(__clang__) && !defined(__GNUC___) && __GNUC__ <= 8
902#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite)
904#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite) \
905 PW_MODIFY_DIAGNOSTICS_PUSH(); \
906 PW_MODIFY_DIAGNOSTIC(ignored, "-Wredundant-decls"); \
907 extern "C" return_type
\
908 PwUnitTestSuiteNamesMustBeUniqueBetweenTESTandTEST_F_##test_suite(void); \
909 PW_MODIFY_DIAGNOSTICS_POP()
918inline void InitGoogleTest(
int*,
char**) {}
Definition: event_handler.h:115
Definition: framework_backend.h:423
Definition: framework_backend.h:761
Definition: framework_backend.h:773
Definition: framework_backend.h:699
Definition: framework_backend.h:649
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
constexpr size_t AlignUp(size_t value, size_t alignment)
Returns the value rounded up to the nearest multiple of alignment.
Definition: alignment.h:38
pw::StringBuilder facilitates creating formatted strings in a fixed-sized buffer or in a pw::InlineSt...
Definition: event_handler.h:52
Definition: event_handler.h:27
Definition: framework_backend.h:408