C/C++ API Reference
Loading...
Searching...
No Matches
framework_backend.h
1// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16// IWYU pragma: private, include "pw_unit_test/framework.h"
17
18#if defined(GTEST_TEST)
19#error \
20 "GTEST_TEST is already defined. Make sure googletest headers are not " \
21 "included when using the pw_unit_test light backend."
22#endif // GTEST_TEST
23
24#include <cstddef>
25#include <cstdint>
26#include <cstring>
27#include <new>
28#include <string_view>
29
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"
39
41
44#define GTEST_TEST(test_suite_name, test_name) \
45 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(void /* TEST */, test_suite_name); \
46 _PW_TEST(test_suite_name, test_name, ::pw::unit_test::internal::Test)
47
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)
59#endif // !GTEST_DONT_DEFINE_TEST
60
71#define TEST_F(test_fixture, test_name) \
72 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(int /* TEST_F */, test_fixture); \
73 _PW_TEST(test_fixture, test_name, test_fixture)
74
84#define FRIEND_TEST(test_suite_name, test_name) \
85 friend class test_suite_name##_##test_name##_Test
86
88
90
95#define EXPECT_TRUE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, true))
96
101#define EXPECT_FALSE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, false))
102
116#define EXPECT_EQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, ==))
117
127
130#define EXPECT_NE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, !=))
131
137#define EXPECT_GT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >))
138
144#define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=))
145
151#define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <))
152
158#define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=))
159
167#define EXPECT_NEAR(lhs, rhs, epsilon) \
168 _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon))
169
176#define EXPECT_FLOAT_EQ(lhs, rhs) \
177 _PW_TEST_EXPECT( \
178 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
179
186#define EXPECT_DOUBLE_EQ(lhs, rhs) \
187 _PW_TEST_EXPECT( \
188 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
189
195#define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==))
196
202#define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=))
203
205
207
210#define ASSERT_TRUE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, true))
211
214#define ASSERT_FALSE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, false))
215
218#define ASSERT_EQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, ==))
219
222#define ASSERT_NE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, !=))
223
226#define ASSERT_GT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >))
227
230#define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=))
231
234#define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <))
235
238#define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=))
239
242#define ASSERT_NEAR(lhs, rhs, epsilon) \
243 _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon))
244
247#define ASSERT_FLOAT_EQ(lhs, rhs) \
248 _PW_TEST_ASSERT( \
249 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
250
253#define ASSERT_DOUBLE_EQ(lhs, rhs) \
254 _PW_TEST_ASSERT( \
255 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
256
259#define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==))
260
263#define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=))
264
266
268
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)", \
276 __FILE__, \
277 __LINE__, \
278 false)
279
283#define GTEST_FAIL() return ADD_FAILURE()
284
288#define GTEST_SKIP() \
289 return ::pw::unit_test::internal::ReturnHelper() = \
290 ::pw::unit_test::internal::Framework::Get().CurrentTestSkip( \
291 __FILE__, __LINE__)
292
298#if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
299#define FAIL() GTEST_FAIL()
300#endif // !GTEST_DONT_DEFINE_FAIL
301
305#define GTEST_SUCCEED() \
306 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
307 "(success)", "(success)", __FILE__, __LINE__, true)
308
315#if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
316#define SUCCEED() GTEST_SUCCEED()
317#endif // !GTEST_DONT_DEFINE_SUCCEED
318
321// TODO: https://pwbug.dev/441096262 - Add SCOPED_TRACE support.
322#define SCOPED_TRACE(message)
323
331int RUN_ALL_TESTS();
332
335#define GTEST_HAS_DEATH_TEST 0
336
339#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
340 if (0) { \
341 static_cast<void>(statement); \
342 static_cast<void>(regex); \
343 } \
344 static_assert(true, "Macros must be terminated with a semicolon")
345
348#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
349 EXPECT_DEATH_IF_SUPPORTED(statement, regex)
350
352
353namespace pw {
354namespace string {
355
357
358// This function is used to print unknown types that are used in EXPECT or
359// ASSERT statements in tests.
360//
361// You can add support for displaying custom types by defining a ToString
362// template specialization. For example:
363//
364// namespace pw {
365//
366// template <>
367// StatusWithSize ToString<MyType>(const MyType& value,
368// span<char> buffer) {
369// return string::Format("<MyType|%d>", value.id);
370// }
371//
372// } // namespace pw
373//
374// See the documentation in pw_string/string_builder.h for more information.
375template <typename T>
376StatusWithSize UnknownTypeToString(const T& value, span<char> buffer) {
377 StringBuilder sb(buffer);
378 sb << '<' << sizeof(value) << "-byte object at 0x" << &value;
379
380 // How many bytes of the object to print.
381 //
382 // WARNING: Printing the contents of an object may be undefined behavior!
383 // Accessing uninitialized memory is undefined behavior, and objects
384 // sometimes contain uninitialized regions, such as padding bytes or
385 // unallocated storage (e.g. std::optional). kPrintMaybeUninitializedBytes
386 // MUST stay at 0, except when changed locally to help with debugging.
387 constexpr size_t kPrintMaybeUnintializedBytes = 0;
388
389 constexpr size_t kBytesToPrint =
390 std::min(sizeof(value), kPrintMaybeUnintializedBytes);
391
392 if (kBytesToPrint != 0u) {
393 sb << " |";
394
395 // reinterpret_cast to std::byte is permitted by C++'s type aliasing
396 // rules.
397 const std::byte* bytes = reinterpret_cast<const std::byte*>(&value);
398
399 for (size_t i = 0; i < kBytesToPrint; ++i) {
400 sb << ' ' << bytes[i];
401 }
402
403 // If there's just one more byte, output it. Otherwise, output ellipsis.
404 if (sizeof(value) == kBytesToPrint + 1) {
405 sb << ' ' << bytes[sizeof(value) - 1];
406 } else if (sizeof(value) > kBytesToPrint) {
407 sb << " …";
408 }
409 }
410
411 sb << '>';
412 return sb.status_with_size();
413}
414
416
417} // namespace string
418
419namespace unit_test {
420namespace internal {
421
422class Test;
423class TestInfo;
424
425// Types of SetUpTestSuite() and TearDownTestSuite() functions.
426using SetUpTestSuiteFunc = void (*)();
427using TearDownTestSuiteFunc = void (*)();
428
429// Used to tag arguments to EXPECT_STREQ/EXPECT_STRNE so they are treated like
430// C strings rather than pointers.
432 const char* const c_str;
433};
434
435constexpr size_t MaxPaddingNeededToRaiseAlignment(size_t current_align,
436 size_t new_align) {
437 if (new_align < current_align) {
438 return 0;
439 }
440 return new_align - current_align;
441}
442
443// GoogleTest supports stream-style messages, but pw_unit_test does not. This
444// class accepts and ignores C++ <<-style logs.
446 public:
447 constexpr FailureMessageAdapter() = default;
448
449 template <typename T>
450 constexpr const FailureMessageAdapter& operator<<(const T&) const {
451 return *this;
452 }
453};
454
455// Used to ignore a stream-style message in an assert, which returns. This
456// uses a similar approach as upstream GoogleTest, but drops any messages.
458 public:
459 constexpr ReturnHelper() = default;
460
461 // Return void so that assigning to ReturnHelper converts the log expression
462 // to void without blocking the stream-style log with a closing parenthesis.
463 // NOLINTNEXTLINE(misc-unconventional-assign-operator)
464 constexpr void operator=(const FailureMessageAdapter&) const {}
465};
466
467// Singleton test framework class responsible for managing and running test
468// cases. This implementation is internal to Pigweed test; free functions
469// wrapping its functionality are exposed as the public interface.
471 public:
472 constexpr Framework()
473 : current_test_(nullptr),
474 current_result_(TestResult::kSuccess),
475 run_tests_summary_{.passed_tests = 0,
476 .failed_tests = 0,
477 .skipped_tests = 0,
478 .disabled_tests = 0},
479 exit_status_(0),
480 event_handler_(nullptr),
481 memory_pool_() {}
482
483 static Framework& Get() { return framework_; }
484
485 // Registers a single test case with the framework. The framework owns the
486 // registered unit test. Called during static initialization.
487 void RegisterTest(TestInfo* test) const;
488
489 // Sets the handler to which the framework dispatches test events. During a
490 // test run, the framework owns the event handler.
491 inline void RegisterEventHandler(EventHandler* event_handler) {
492 event_handler_ = event_handler;
493 }
494
495 // Runs all registered test cases, returning a status of 0 if all succeeded
496 // or nonzero if there were any failures. Test events that occur during the
497 // run are sent to the registered event handler, if any.
498 int RunAllTests();
499
500 // Only run test suites whose names are included in the provided list during
501 // the next test run.
502 void SetTestSuitesToRun(span<std::string_view> test_suites) {
503 test_suites_to_run_ = test_suites;
504 }
505
506 bool ShouldRunTest(const TestInfo& test_info) const;
507
508 // Whether the current test is skipped.
509 bool IsSkipped() const { return current_result_ == TestResult::kSkipped; }
510
511 // Whether the current test has failed.
512 bool HasFailure() const { return current_result_ == TestResult::kFailure; }
513
514 // Constructs an instance of a unit test class and runs the test.
515 //
516 // Tests are constructed within a static memory pool at run time instead of
517 // being statically allocated to avoid blowing up the size of the test
518 // binary in cases where users have large test fixtures (e.g. containing
519 // buffers) reused many times. Instead, only a small, fixed-size TestInfo
520 // struct is statically allocated per test case, with a run() function that
521 // references this method instantiated for its test class.
522 template <typename TestInstance>
523 static void CreateAndRunTest(const TestInfo& test_info) {
524 static_assert(
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 "
531 "test fixture.");
532
533 Framework& framework = Get();
534 framework.StartTest(test_info);
535
536 // Reset the memory pool to a marker value to help detect use of
537 // uninitialized memory.
538 std::memset(&framework.memory_pool_, 0xa5, sizeof(framework.memory_pool_));
539
540 framework.SetUpTestSuiteIfNeeded(TestInstance::SetUpTestSuite);
541
542 // Construct the test object within the static memory pool. The StartTest
543 // function has already been called by the TestInfo at this point.
544 void* aligned_pool =
545 AlignUp(&framework.memory_pool_, alignof(TestInstance));
546 TestInstance* test_instance = new (aligned_pool) TestInstance();
547 test_instance->PigweedTestRun();
548
549 // Manually call the destructor as it is not called automatically for
550 // objects constructed using placement new.
551 test_instance->~TestInstance();
552
553 framework.TearDownTestSuiteIfNeeded(TestInstance::TearDownTestSuite);
554
555 framework.EndCurrentTest();
556 }
557
558 template <typename Expectation, typename Lhs, typename Rhs, typename Epsilon>
559 [[nodiscard]] bool CurrentTestExpectWithEpsilon(Expectation expectation,
560 const Lhs& lhs,
561 const Rhs& rhs,
562 const Epsilon& epsilon,
563 const char* expression,
564 const char* file,
565 int line) {
566 const bool success = expectation(lhs, rhs, epsilon);
567 if (!success) {
568 CurrentTestExpectSimple(expression,
569 MakeString<config::kExpectationBufferSizeBytes>(
570 ConvertForPrint(lhs),
571 " within ",
572 ConvertForPrint(epsilon),
573 " of ",
574 ConvertForPrint(rhs))
575 .c_str(),
576 file,
577 line,
578 success);
579 }
580 return success;
581 }
582
583 // Runs an expectation function for the currently active test case.
584 template <typename Expectation, typename Lhs, typename Rhs>
585 [[nodiscard]] bool CurrentTestExpect(Expectation expectation,
586 const Lhs& lhs,
587 const Rhs& rhs,
588 const char* expectation_string,
589 const char* expression,
590 const char* file,
591 int line) {
592 const bool success = expectation(lhs, rhs);
593 if (!success) {
594 CurrentTestExpectSimple(
595 expression,
596 MakeString<config::kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
597 ' ',
598 expectation_string,
599 ' ',
600 ConvertForPrint(rhs))
601 .c_str(),
602 file,
603 line,
604 success);
605 }
606 return success;
607 }
608
609 // Skips the current test and dispatches an event for it.
611 const char* file, int line);
612
613 // Dispatches an event indicating the result of an expectation.
615 const char* expression,
616 const char* evaluated_expression,
617 const char* file,
618 int line,
619 bool success);
620
621 private:
622 // Convert char* to void* so that they are printed as pointers instead of
623 // strings in EXPECT_EQ and other macros. EXPECT_STREQ wraps its pointers in
624 // a CStringArg so its pointers are treated like C strings.
625 static constexpr const void* ConvertForPrint(const char* str) { return str; }
626
627 static constexpr const void* ConvertForPrint(char* str) { return str; }
628
629 static constexpr const char* ConvertForPrint(CStringArg value) {
630 return value.c_str;
631 }
632
633 template <typename T>
634 static constexpr T ConvertForPrint(T&& value) {
635 return std::forward<T>(value);
636 }
637
638 // If current_test_ will be first of its suite, call set_up_ts
639 void SetUpTestSuiteIfNeeded(SetUpTestSuiteFunc set_up_ts) const;
640
641 // If current_test_ was the last of its suite, call tear_down_ts
642 void TearDownTestSuiteIfNeeded(TearDownTestSuiteFunc tear_down_ts) const;
643
644 // Sets current_test_ and dispatches an event indicating that a test
645 // started.
646 void StartTest(const TestInfo& test);
647
648 // Dispatches event indicating that a test finished and clears
649 // current_test_.
650 void EndCurrentTest();
651
652 // Singleton instance of the framework class.
653 static Framework framework_;
654
655 // Linked list of all registered test cases. This is static as it tests are
656 // registered using static initialization.
657 static TestInfo* tests_;
658
659 // The current test case which is running.
660 const TestInfo* current_test_;
661
662 // Overall result of the current test case (pass/fail/skip).
663 TestResult current_result_;
664
665 // Overall result of the ongoing test run, which covers multiple tests.
666 RunTestsSummary run_tests_summary_;
667
668 // Program exit status returned by RunAllTests for GoogleTest compatibility.
669 int exit_status_;
670
671 // Handler to which to dispatch test events.
672 EventHandler* event_handler_;
673
674 span<std::string_view> test_suites_to_run_;
675
676 alignas(std::max_align_t) std::byte memory_pool_[config::kMemoryPoolSize];
677};
678
679// Information about a single test case, including a pointer to a function
680// which constructs and runs the test class. These are statically allocated
681// instead of the test classes, as test classes can be very large.
682class TestInfo {
683 public:
684 TestInfo(const char* const test_suite_name,
685 const char* const test_name,
686 const char* const file_name,
687 void (*run_func)(const TestInfo&))
688 : test_case_{
689 .suite_name = test_suite_name,
690 .test_name = test_name,
691 .file_name = file_name,
692 }, run_(run_func) {
693 Framework::Get().RegisterTest(this);
694 }
695
696 // The name of the suite to which the test case belongs, the name of the
697 // test case itself, and the path to the file in which the test case is
698 // located.
699 const TestCase& test_case() const { return test_case_; }
700
701 bool enabled() const;
702
703 void run() const { run_(*this); }
704
705 TestInfo* next() const { return next_; }
706 void set_next(TestInfo* next) { next_ = next; }
707
708 private:
709 TestCase test_case_;
710
711 // Function which runs the test case. Refers to Framework::CreateAndRunTest
712 // instantiated for the test case's class.
713 void (*run_)(const TestInfo&);
714
715 // TestInfo structs are registered with the test framework and stored as a
716 // linked list.
717 TestInfo* next_ = nullptr;
718};
719
720// Base class for all test cases or custom test fixtures.
721// Every unit test created using the TEST or TEST_F macro defines a class that
722// inherits from this (or a subclass of this).
723//
724// For example, given the following test definition:
725//
726// TEST(MyTest, SaysHello) {
727// ASSERT_STREQ(SayHello(), "Hello, world!");
728// }
729//
730// A new class is defined for the test, e.g. MyTest_SaysHello_Test. This class
731// inherits from the Test class and implements its PigweedTestBody function
732// with the block provided to the TEST macro.
733class Test {
734 public:
735 Test(const Test&) = delete;
736 Test& operator=(const Test&) = delete;
737
738 virtual ~Test() = default;
739
740 static void SetUpTestSuite() {}
741 static void TearDownTestSuite() {}
742
743 static bool HasFailure() { return Framework::Get().HasFailure(); }
744
745 // Runs the unit test.
746 void PigweedTestRun() {
747 SetUp();
748 if (!HasFailure() && !Framework::Get().IsSkipped()) {
749 PigweedTestBody();
750 }
751 TearDown();
752 }
753
754 protected:
755 Test() = default;
756
757 // Called immediately before executing the test body.
758 //
759 // Setup and cleanup can typically be done in the test fixture's constructor
760 // and destructor, but there are cases where SetUp/TearDown must be used
761 // instead. See the Google Test documentation for more information.
762 virtual void SetUp() {}
763
764 // Called immediately after executing the test body.
765 virtual void TearDown() {}
766
767 private:
768 friend class internal::Framework;
769
770 // The user-provided body of the test case. Populated by the TEST macro.
771 virtual void PigweedTestBody() = 0;
772};
773
774// Checks that a test suite name is valid.
775constexpr bool HasNoUnderscores(const char* suite) {
776 const char* disabled_prefix = "DISABLED_";
777
778 for (; *suite != '\0'; ++suite) {
779 if (*suite == *disabled_prefix) {
780 disabled_prefix += 1;
781 } else {
782 disabled_prefix = "";
783 if (*suite == '_') {
784 return false;
785 }
786 }
787 }
788 return true;
789}
790
791} // namespace internal
792
793inline void SetTestSuitesToRun(span<std::string_view> test_suites) {
794 internal::Framework::Get().SetTestSuitesToRun(test_suites);
795}
796
797} // namespace unit_test
798} // namespace pw
799
800inline int RUN_ALL_TESTS() {
801 return ::pw::unit_test::internal::Framework::Get().RunAllTests();
802}
803
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"); \
811 \
812 _PW_TEST_CLASS(test_suite_name, \
813 test_name, \
814 test_suite_name##_##test_name##_Test, \
815 parent_class)
816
817#define _PW_TEST_CLASS(suite, name, class_name, parent_class) \
818 class class_name final : public parent_class { \
819 private: \
820 void PigweedTestBody() override; \
821 }; \
822 \
823 extern "C" { \
824 \
825 /* Silence ASAN to avoid errors in the initialization order checker */ \
826 /* caused by the intentional use of dynamic initializers which modify */ \
827 /* other globals */ \
828 PW_NO_SANITIZE("address") \
829 /* Declare the TestInfo as non-const since const variables do not work */ \
830 /* with the PW_UNIT_TEST_LINK_FILE_CONTAINING_TEST macro. */ \
831 /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ \
832 ::pw::unit_test::internal::TestInfo _pw_unit_test_Info_##suite##_##name( \
833 #suite, \
834 #name, \
835 __FILE__, \
836 ::pw::unit_test::internal::Framework::CreateAndRunTest<class_name>); \
837 \
838 } /* extern "C" */ \
839 \
840 void class_name::PigweedTestBody()
841
842#define _PW_TEST_ASSERT(expectation) \
843 if (!(expectation)) \
844 return ::pw::unit_test::internal::ReturnHelper() = \
845 ::pw::unit_test::internal::FailureMessageAdapter()
846
847#define _PW_TEST_EXPECT(expectation) \
848 if (!(expectation)) \
849 ::pw::unit_test::internal::FailureMessageAdapter()
850
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), \
855 value, \
856 "is", \
857 #expr " is " #value, \
858 __FILE__, \
859 __LINE__)
860
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; \
865 }, \
866 (lhs), \
867 (rhs), \
868 #op, \
869 #lhs " " #op " " #rhs, \
870 __FILE__, \
871 __LINE__)
872
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; \
877 }, \
878 (lhs), \
879 (rhs), \
880 (epsilon), \
881 #lhs " within " #epsilon " of " #rhs, \
882 __FILE__, \
883 __LINE__)
884
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 { \
889 if (!l || !r) { \
890 return l != r; \
891 } \
892 return std::strcmp(l, r); \
893 }; \
894 return cmp(_pw_lhs.c_str, _pw_rhs.c_str) op 0; \
895 }, \
896 ::pw::unit_test::internal::CStringArg{lhs}, \
897 ::pw::unit_test::internal::CStringArg{rhs}, \
898 #op, \
899 #lhs " " #op " " #rhs, \
900 __FILE__, \
901 __LINE__)
902
903// Checks that test suite names between TEST and TEST_F declarations are unique.
904// This works by declaring a function named for the test suite. The function
905// takes no arguments but is declared with different return types in the TEST
906// and TEST_F macros. If a TEST and TEST_F use the same test suite name, the
907// function declarations conflict, resulting in a compilation error.
908//
909// This catches most conflicts, but a runtime check is ultimately needed since
910// tests may be declared in different translation units.
911#if !defined(__clang__) && !defined(__GNUC___) && __GNUC__ <= 8
912// For some reason GCC8 is unable to ignore -Wredundant-decls here.
913#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite)
914#else // All other compilers.
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 /* use extern "C" to escape namespacing */ \
919 PwUnitTestSuiteNamesMustBeUniqueBetweenTESTandTEST_F_##test_suite(void); \
920 PW_MODIFY_DIAGNOSTICS_POP()
921#endif // GCC8 or older.
922
923namespace testing {
924
925// Alias Test as ::testing::Test for GoogleTest compatibility.
927
928// Provide a no-op init routine for GoogleTest compatibility.
929inline void InitGoogleTest(int*, char**) {}
930
931} // namespace testing
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