18#if defined(GTEST_TEST)
20 "GTEST_TEST is already defined. Make sure googletest headers are not " \
21 "included when using the pw_unit_test light backend."
30#include "pw_bytes/alignment.h"
31#include "pw_polyfill/standard.h"
32#include "pw_preprocessor/compiler.h"
33#include "pw_preprocessor/util.h"
34#include "pw_span/span.h"
35#include "pw_status/status.h"
37#include "pw_unit_test/config.h"
38#include "pw_unit_test/event_handler.h"
44#define GTEST_TEST(test_suite_name, test_name) \
45 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(void , test_suite_name); \
46 _PW_TEST(test_suite_name, test_name, ::pw::unit_test::internal::Test)
57#if !(defined(GTEST_DONT_DEFINE_TEST) && GTEST_DONT_DEFINE_TEST)
58#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
71#define TEST_F(test_fixture, test_name) \
72 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(int , test_fixture); \
73 _PW_TEST(test_fixture, test_name, test_fixture)
84#define FRIEND_TEST(test_suite_name, test_name) \
85 friend class test_suite_name##_##test_name##_Test
95#define EXPECT_TRUE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, true))
101#define EXPECT_FALSE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, false))
116#define EXPECT_EQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, ==))
130#define EXPECT_NE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, !=))
137#define EXPECT_GT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >))
144#define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=))
151#define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <))
158#define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=))
167#define EXPECT_NEAR(lhs, rhs, epsilon) \
168 _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon))
176#define EXPECT_FLOAT_EQ(lhs, rhs) \
178 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
186#define EXPECT_DOUBLE_EQ(lhs, rhs) \
188 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
195#define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==))
202#define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=))
210#define ASSERT_TRUE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, true))
214#define ASSERT_FALSE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, false))
218#define ASSERT_EQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, ==))
222#define ASSERT_NE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, !=))
226#define ASSERT_GT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >))
230#define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=))
234#define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <))
238#define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=))
242#define ASSERT_NEAR(lhs, rhs, epsilon) \
243 _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon))
247#define ASSERT_FLOAT_EQ(lhs, rhs) \
249 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
253#define ASSERT_DOUBLE_EQ(lhs, rhs) \
255 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
259#define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==))
263#define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=))
271#define ADD_FAILURE() \
272 ::pw::unit_test::internal::ReturnHelper() = \
273 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
274 "(line is not executed)", \
275 "(line was executed)", \
283#define GTEST_FAIL() return ADD_FAILURE()
288#define GTEST_SKIP() \
289 return ::pw::unit_test::internal::ReturnHelper() = \
290 ::pw::unit_test::internal::Framework::Get().CurrentTestSkip( \
298#if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
299#define FAIL() GTEST_FAIL()
305#define GTEST_SUCCEED() \
306 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
307 "(success)", "(success)", __FILE__, __LINE__, true)
315#if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
316#define SUCCEED() GTEST_SUCCEED()
322#define SCOPED_TRACE(message)
335#define GTEST_HAS_DEATH_TEST 0
339#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
341 static_cast<void>(statement); \
342 static_cast<void>(regex); \
344 static_assert(true, "Macros must be terminated with a semicolon")
348#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
349 EXPECT_DEATH_IF_SUPPORTED(statement, regex)
376StatusWithSize UnknownTypeToString(
const T& value, span<char> buffer) {
377 StringBuilder sb(buffer);
378 sb <<
'<' <<
sizeof(value) <<
"-byte object at 0x" << &value;
387 constexpr size_t kPrintMaybeUnintializedBytes = 0;
389 constexpr size_t kBytesToPrint =
390 std::min(
sizeof(value), kPrintMaybeUnintializedBytes);
392 if (kBytesToPrint != 0u) {
397 const std::byte* bytes =
reinterpret_cast<const std::byte*
>(&value);
399 for (
size_t i = 0; i < kBytesToPrint; ++i) {
400 sb <<
' ' << bytes[i];
404 if (
sizeof(value) == kBytesToPrint + 1) {
405 sb <<
' ' << bytes[
sizeof(value) - 1];
406 }
else if (
sizeof(value) > kBytesToPrint) {
412 return sb.status_with_size();
426using SetUpTestSuiteFunc = void (*)();
427using TearDownTestSuiteFunc = void (*)();
432 const char*
const c_str;
435constexpr size_t MaxPaddingNeededToRaiseAlignment(
size_t current_align,
437 if (new_align < current_align) {
440 return new_align - current_align;
449 template <
typename T>
473 : current_test_(
nullptr),
474 current_result_(TestResult::kSuccess),
475 run_tests_summary_{.passed_tests = 0,
478 .disabled_tests = 0},
480 event_handler_(
nullptr),
483 static Framework& Get() {
return framework_; }
487 void RegisterTest(
TestInfo* test)
const;
491 inline void RegisterEventHandler(
EventHandler* event_handler) {
492 event_handler_ = event_handler;
503 test_suites_to_run_ = test_suites;
506 bool ShouldRunTest(
const TestInfo& test_info)
const;
509 bool IsSkipped()
const {
return current_result_ == TestResult::kSkipped; }
512 bool HasFailure()
const {
return current_result_ == TestResult::kFailure; }
522 template <
typename TestInstance>
523 static void CreateAndRunTest(
const TestInfo& test_info) {
525 sizeof(TestInstance) +
526 MaxPaddingNeededToRaiseAlignment(
527 alignof(
decltype(memory_pool_)),
alignof(TestInstance)) <=
528 sizeof(memory_pool_),
529 "The test memory pool is too small for this test. Either increase "
530 "PW_UNIT_TEST_CONFIG_MEMORY_POOL_SIZE or decrease the size of your "
534 framework.StartTest(test_info);
538 std::memset(&framework.memory_pool_, 0xa5,
sizeof(framework.memory_pool_));
540 framework.SetUpTestSuiteIfNeeded(TestInstance::SetUpTestSuite);
545 AlignUp(&framework.memory_pool_,
alignof(TestInstance));
546 TestInstance* test_instance =
new (aligned_pool) TestInstance();
547 test_instance->PigweedTestRun();
551 test_instance->~TestInstance();
553 framework.TearDownTestSuiteIfNeeded(TestInstance::TearDownTestSuite);
555 framework.EndCurrentTest();
558 template <
typename Expectation,
typename Lhs,
typename Rhs,
typename Epsilon>
559 [[nodiscard]]
bool CurrentTestExpectWithEpsilon(Expectation expectation,
562 const Epsilon& epsilon,
563 const char* expression,
566 const bool success = expectation(lhs, rhs, epsilon);
568 CurrentTestExpectSimple(expression,
569 MakeString<config::kExpectationBufferSizeBytes>(
570 ConvertForPrint(lhs),
572 ConvertForPrint(epsilon),
574 ConvertForPrint(rhs))
584 template <
typename Expectation,
typename Lhs,
typename Rhs>
585 [[nodiscard]]
bool CurrentTestExpect(Expectation expectation,
588 const char* expectation_string,
589 const char* expression,
592 const bool success = expectation(lhs, rhs);
594 CurrentTestExpectSimple(
596 MakeString<config::kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
600 ConvertForPrint(rhs))
611 const char* file,
int line);
615 const char* expression,
616 const char* evaluated_expression,
625 static constexpr const void* ConvertForPrint(
const char* str) {
return str; }
627 static constexpr const void* ConvertForPrint(
char* str) {
return str; }
629 static constexpr const char* ConvertForPrint(
CStringArg value) {
633 template <
typename T>
634 static constexpr T ConvertForPrint(T&& value) {
635 return std::forward<T>(value);
639 void SetUpTestSuiteIfNeeded(SetUpTestSuiteFunc set_up_ts)
const;
642 void TearDownTestSuiteIfNeeded(TearDownTestSuiteFunc tear_down_ts)
const;
646 void StartTest(
const TestInfo& test);
650 void EndCurrentTest();
676 alignas(std::max_align_t) std::byte memory_pool_[config::kMemoryPoolSize];
684 TestInfo(
const char*
const test_suite_name,
685 const char*
const test_name,
686 const char*
const file_name,
689 .suite_name = test_suite_name,
690 .test_name = test_name,
691 .file_name = file_name,
693 Framework::Get().RegisterTest(
this);
699 const TestCase& test_case()
const {
return test_case_; }
701 bool enabled()
const;
703 void run()
const { run_(*
this); }
705 TestInfo* next()
const {
return next_; }
706 void set_next(
TestInfo* next) { next_ = next; }
736 Test& operator=(
const Test&) =
delete;
738 virtual ~Test() =
default;
740 static void SetUpTestSuite() {}
741 static void TearDownTestSuite() {}
743 static bool HasFailure() {
return Framework::Get().HasFailure(); }
746 void PigweedTestRun() {
748 if (!HasFailure() && !Framework::Get().IsSkipped()) {
762 virtual void SetUp() {}
765 virtual void TearDown() {}
771 virtual void PigweedTestBody() = 0;
775constexpr bool HasNoUnderscores(
const char* suite) {
776 const char* disabled_prefix =
"DISABLED_";
778 for (; *suite !=
'\0'; ++suite) {
779 if (*suite == *disabled_prefix) {
780 disabled_prefix += 1;
782 disabled_prefix =
"";
793inline void SetTestSuitesToRun(span<std::string_view> test_suites) {
794 internal::Framework::Get().SetTestSuitesToRun(test_suites);
801 return ::pw::unit_test::internal::Framework::Get().RunAllTests();
804#define _PW_TEST(test_suite_name, test_name, parent_class) \
805 static_assert(sizeof(#test_suite_name) > 1, \
806 "The test suite name must not be empty"); \
807 static_assert(::pw::unit_test::internal::HasNoUnderscores(#test_suite_name), \
808 "The test suite name (" #test_suite_name \
809 ") cannot contain underscores"); \
810 static_assert(sizeof(#test_name) > 1, "The test name must not be empty"); \
812 _PW_TEST_CLASS(test_suite_name, \
814 test_suite_name##_##test_name##_Test, \
817#define _PW_TEST_CLASS(suite, name, class_name, parent_class) \
818 class class_name final : public parent_class { \
820 void PigweedTestBody() override; \
828 PW_NO_SANITIZE("address") \
832 ::pw::unit_test::internal::TestInfo _pw_unit_test_Info_##suite##_##name( \
836 ::pw::unit_test::internal::Framework::CreateAndRunTest<class_name>); \
840 void class_name::PigweedTestBody()
842#define _PW_TEST_ASSERT(expectation) \
843 if (!(expectation)) \
844 return ::pw::unit_test::internal::ReturnHelper() = \
845 ::pw::unit_test::internal::FailureMessageAdapter()
847#define _PW_TEST_EXPECT(expectation) \
848 if (!(expectation)) \
849 ::pw::unit_test::internal::FailureMessageAdapter()
851#define _PW_TEST_BOOL(expr, value) \
852 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
853 [](bool _pw_lhs, bool _pw_rhs) { return _pw_lhs == _pw_rhs; }, \
854 static_cast<bool>(expr), \
857 #expr " is " #value, \
861#define _PW_TEST_OP(lhs, rhs, op) \
862 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
863 [](const auto& _pw_lhs, const auto& _pw_rhs) { \
864 return _pw_lhs op _pw_rhs; \
869 #lhs " " #op " " #rhs, \
873#define _PW_TEST_NEAR(lhs, rhs, epsilon) \
874 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectWithEpsilon( \
875 [](const auto& _pw_lhs, const auto& _pw_rhs, const auto& _pw_epsilon) { \
876 return std::abs(_pw_lhs - _pw_rhs) <= _pw_epsilon; \
881 #lhs " within " #epsilon " of " #rhs, \
885#define _PW_TEST_C_STR(lhs, rhs, op) \
886 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
887 [](const auto& _pw_lhs, const auto& _pw_rhs) { \
888 auto cmp = [](const char* l, const char* r) -> int { \
892 return std::strcmp(l, r); \
894 return cmp(_pw_lhs.c_str, _pw_rhs.c_str) op 0; \
896 ::pw::unit_test::internal::CStringArg{lhs}, \
897 ::pw::unit_test::internal::CStringArg{rhs}, \
899 #lhs " " #op " " #rhs, \
911#if !defined(__clang__) && !defined(__GNUC___) && __GNUC__ <= 8
913#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite)
915#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite) \
916 PW_MODIFY_DIAGNOSTICS_PUSH(); \
917 PW_MODIFY_DIAGNOSTIC(ignored, "-Wredundant-decls"); \
918 extern "C" return_type
\
919 PwUnitTestSuiteNamesMustBeUniqueBetweenTESTandTEST_F_##test_suite(void); \
920 PW_MODIFY_DIAGNOSTICS_POP()
929inline void InitGoogleTest(
int*,
char**) {}
Definition: span_impl.h:235
Definition: event_handler.h:122
Definition: framework_backend.h:445
Definition: framework_backend.h:470
Definition: framework_backend.h:457
Definition: framework_backend.h:733
Definition: framework_backend.h:682
constexpr size_t AlignUp(uintptr_t value, size_t alignment)
Returns the value rounded up to the nearest multiple of alignment.
Definition: alignment.h:54
int RUN_ALL_TESTS()
Definition: framework_backend.h:800
TestResult
The result of a complete test run.
Definition: event_handler.h:23
The Pigweed namespace.
Definition: alignment.h:27
pw::StringBuilder facilitates creating formatted strings in a fixed-sized buffer or in a pw::InlineSt...
Definition: event_handler.h:59
Definition: event_handler.h:30
Definition: framework_backend.h:431