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
42#define GTEST_TEST(test_suite_name, test_name) \
43 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(void /* TEST */, test_suite_name); \
44 _PW_TEST(test_suite_name, test_name, ::pw::unit_test::internal::Test)
45
55#if !(defined(GTEST_DONT_DEFINE_TEST) && GTEST_DONT_DEFINE_TEST)
56#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
57#endif // !GTEST_DONT_DEFINE_TEST
58
64#define TEST_F(test_fixture, test_name) \
65 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(int /* TEST_F */, test_fixture); \
66 _PW_TEST(test_fixture, test_name, test_fixture)
67
77#define FRIEND_TEST(test_suite_name, test_name) \
78 friend class test_suite_name##_##test_name##_Test
79
84#define EXPECT_TRUE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, true))
85
90#define EXPECT_FALSE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, false))
91
105#define EXPECT_EQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, ==))
106
116
119#define EXPECT_NE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, !=))
120
126#define EXPECT_GT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >))
127
133#define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=))
134
140#define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <))
141
147#define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=))
148
156#define EXPECT_NEAR(lhs, rhs, epsilon) \
157 _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon))
158
165#define EXPECT_FLOAT_EQ(lhs, rhs) \
166 _PW_TEST_EXPECT( \
167 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
168
175#define EXPECT_DOUBLE_EQ(lhs, rhs) \
176 _PW_TEST_EXPECT( \
177 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
178
184#define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==))
185
191#define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=))
192
195#define ASSERT_TRUE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, true))
196
199#define ASSERT_FALSE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, false))
200
203#define ASSERT_EQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, ==))
204
207#define ASSERT_NE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, !=))
208
211#define ASSERT_GT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >))
212
215#define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=))
216
219#define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <))
220
223#define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=))
224
227#define ASSERT_NEAR(lhs, rhs, epsilon) \
228 _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon))
229
232#define ASSERT_FLOAT_EQ(lhs, rhs) \
233 _PW_TEST_ASSERT( \
234 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
235
238#define ASSERT_DOUBLE_EQ(lhs, rhs) \
239 _PW_TEST_ASSERT( \
240 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
241
244#define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==))
245
248#define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=))
249
252#define ADD_FAILURE() \
253 ::pw::unit_test::internal::ReturnHelper() = \
254 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
255 "(line is not executed)", "(line was executed)", __LINE__, false)
256
260#define GTEST_FAIL() return ADD_FAILURE()
261
265#define GTEST_SKIP() \
266 return ::pw::unit_test::internal::ReturnHelper() = \
267 ::pw::unit_test::internal::Framework::Get().CurrentTestSkip( \
268 __LINE__)
269
275#if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
276#define FAIL() GTEST_FAIL()
277#endif // !GTEST_DONT_DEFINE_FAIL
278
282#define GTEST_SUCCEED() \
283 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
284 "(success)", "(success)", __LINE__, true)
285
292#if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
293#define SUCCEED() GTEST_SUCCEED()
294#endif // !GTEST_DONT_DEFINE_SUCCEED
295
298// TODO: https://pwbug.dev/441096262 - Add SCOPED_TRACE support.
299#define SCOPED_TRACE(message)
300
308int RUN_ALL_TESTS();
309
312#define GTEST_HAS_DEATH_TEST 0
313
316#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
317 if (0) { \
318 static_cast<void>(statement); \
319 static_cast<void>(regex); \
320 } \
321 static_assert(true, "Macros must be terminated with a semicolon")
322
325#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
326 EXPECT_DEATH_IF_SUPPORTED(statement, regex)
327
328namespace pw {
329namespace string {
330
331// This function is used to print unknown types that are used in EXPECT or
332// ASSERT statements in tests.
333//
334// You can add support for displaying custom types by defining a ToString
335// template specialization. For example:
336//
337// namespace pw {
338//
339// template <>
340// StatusWithSize ToString<MyType>(const MyType& value,
341// span<char> buffer) {
342// return string::Format("<MyType|%d>", value.id);
343// }
344//
345// } // namespace pw
346//
347// See the documentation in pw_string/string_builder.h for more information.
348template <typename T>
349StatusWithSize UnknownTypeToString(const T& value, span<char> buffer) {
350 StringBuilder sb(buffer);
351 sb << '<' << sizeof(value) << "-byte object at 0x" << &value;
352
353 // How many bytes of the object to print.
354 //
355 // WARNING: Printing the contents of an object may be undefined behavior!
356 // Accessing uninitialized memory is undefined behavior, and objects
357 // sometimes contain uninitialized regions, such as padding bytes or
358 // unallocated storage (e.g. std::optional). kPrintMaybeUninitializedBytes
359 // MUST stay at 0, except when changed locally to help with debugging.
360 constexpr size_t kPrintMaybeUnintializedBytes = 0;
361
362 constexpr size_t kBytesToPrint =
363 std::min(sizeof(value), kPrintMaybeUnintializedBytes);
364
365 if (kBytesToPrint != 0u) {
366 sb << " |";
367
368 // reinterpret_cast to std::byte is permitted by C++'s type aliasing
369 // rules.
370 const std::byte* bytes = reinterpret_cast<const std::byte*>(&value);
371
372 for (size_t i = 0; i < kBytesToPrint; ++i) {
373 sb << ' ' << bytes[i];
374 }
375
376 // If there's just one more byte, output it. Otherwise, output ellipsis.
377 if (sizeof(value) == kBytesToPrint + 1) {
378 sb << ' ' << bytes[sizeof(value) - 1];
379 } else if (sizeof(value) > kBytesToPrint) {
380 sb << " …";
381 }
382 }
383
384 sb << '>';
385 return sb.status_with_size();
386}
387
388} // namespace string
389
390namespace unit_test {
391namespace internal {
392
393class Test;
394class TestInfo;
395
396// Types of SetUpTestSuite() and TearDownTestSuite() functions.
397using SetUpTestSuiteFunc = void (*)();
398using TearDownTestSuiteFunc = void (*)();
399
400// Used to tag arguments to EXPECT_STREQ/EXPECT_STRNE so they are treated like
401// C strings rather than pointers.
403 const char* const c_str;
404};
405
406constexpr size_t MaxPaddingNeededToRaiseAlignment(size_t current_align,
407 size_t new_align) {
408 if (new_align < current_align) {
409 return 0;
410 }
411 return new_align - current_align;
412}
413
414// GoogleTest supports stream-style messages, but pw_unit_test does not. This
415// class accepts and ignores C++ <<-style logs.
417 public:
418 constexpr FailureMessageAdapter() = default;
419
420 template <typename T>
421 constexpr const FailureMessageAdapter& operator<<(const T&) const {
422 return *this;
423 }
424};
425
426// Used to ignore a stream-style message in an assert, which returns. This
427// uses a similar approach as upstream GoogleTest, but drops any messages.
429 public:
430 constexpr ReturnHelper() = default;
431
432 // Return void so that assigning to ReturnHelper converts the log expression
433 // to void without blocking the stream-style log with a closing parenthesis.
434 // NOLINTNEXTLINE(misc-unconventional-assign-operator)
435 constexpr void operator=(const FailureMessageAdapter&) const {}
436};
437
438// Singleton test framework class responsible for managing and running test
439// cases. This implementation is internal to Pigweed test; free functions
440// wrapping its functionality are exposed as the public interface.
442 public:
443 constexpr Framework()
444 : current_test_(nullptr),
445 current_result_(TestResult::kSuccess),
446 run_tests_summary_{.passed_tests = 0,
447 .failed_tests = 0,
448 .skipped_tests = 0,
449 .disabled_tests = 0},
450 exit_status_(0),
451 event_handler_(nullptr),
452 memory_pool_() {}
453
454 static Framework& Get() { return framework_; }
455
456 // Registers a single test case with the framework. The framework owns the
457 // registered unit test. Called during static initialization.
458 void RegisterTest(TestInfo* test) const;
459
460 // Sets the handler to which the framework dispatches test events. During a
461 // test run, the framework owns the event handler.
462 inline void RegisterEventHandler(EventHandler* event_handler) {
463 event_handler_ = event_handler;
464 }
465
466 // Runs all registered test cases, returning a status of 0 if all succeeded
467 // or nonzero if there were any failures. Test events that occur during the
468 // run are sent to the registered event handler, if any.
469 int RunAllTests();
470
471 // Only run test suites whose names are included in the provided list during
472 // the next test run.
473 void SetTestSuitesToRun(span<std::string_view> test_suites) {
474 test_suites_to_run_ = test_suites;
475 }
476
477 bool ShouldRunTest(const TestInfo& test_info) const;
478
479 // Whether the current test is skipped.
480 bool IsSkipped() const { return current_result_ == TestResult::kSkipped; }
481
482 // Whether the current test has failed.
483 bool HasFailure() const { return current_result_ == TestResult::kFailure; }
484
485 // Constructs an instance of a unit test class and runs the test.
486 //
487 // Tests are constructed within a static memory pool at run time instead of
488 // being statically allocated to avoid blowing up the size of the test
489 // binary in cases where users have large test fixtures (e.g. containing
490 // buffers) reused many times. Instead, only a small, fixed-size TestInfo
491 // struct is statically allocated per test case, with a run() function that
492 // references this method instantiated for its test class.
493 template <typename TestInstance>
494 static void CreateAndRunTest(const TestInfo& test_info) {
495 static_assert(
496 sizeof(TestInstance) +
497 MaxPaddingNeededToRaiseAlignment(
498 alignof(decltype(memory_pool_)), alignof(TestInstance)) <=
499 sizeof(memory_pool_),
500 "The test memory pool is too small for this test. Either increase "
501 "PW_UNIT_TEST_CONFIG_MEMORY_POOL_SIZE or decrease the size of your "
502 "test fixture.");
503
504 Framework& framework = Get();
505 framework.StartTest(test_info);
506
507 // Reset the memory pool to a marker value to help detect use of
508 // uninitialized memory.
509 std::memset(&framework.memory_pool_, 0xa5, sizeof(framework.memory_pool_));
510
511 framework.SetUpTestSuiteIfNeeded(TestInstance::SetUpTestSuite);
512
513 // Construct the test object within the static memory pool. The StartTest
514 // function has already been called by the TestInfo at this point.
515 void* aligned_pool =
516 AlignUp(&framework.memory_pool_, alignof(TestInstance));
517 TestInstance* test_instance = new (aligned_pool) TestInstance();
518 test_instance->PigweedTestRun();
519
520 // Manually call the destructor as it is not called automatically for
521 // objects constructed using placement new.
522 test_instance->~TestInstance();
523
524 framework.TearDownTestSuiteIfNeeded(TestInstance::TearDownTestSuite);
525
526 framework.EndCurrentTest();
527 }
528
529 template <typename Expectation, typename Lhs, typename Rhs, typename Epsilon>
530 [[nodiscard]] bool CurrentTestExpectWithEpsilon(Expectation expectation,
531 const Lhs& lhs,
532 const Rhs& rhs,
533 const Epsilon& epsilon,
534 const char* expression,
535 int line) {
536 const bool success = expectation(lhs, rhs, epsilon);
537 if (!success) {
538 CurrentTestExpectSimple(expression,
539 MakeString<config::kExpectationBufferSizeBytes>(
540 ConvertForPrint(lhs),
541 " within ",
542 ConvertForPrint(epsilon),
543 " of ",
544 ConvertForPrint(rhs))
545 .c_str(),
546 line,
547 success);
548 }
549 return success;
550 }
551
552 // Runs an expectation function for the currently active test case.
553 template <typename Expectation, typename Lhs, typename Rhs>
554 [[nodiscard]] bool CurrentTestExpect(Expectation expectation,
555 const Lhs& lhs,
556 const Rhs& rhs,
557 const char* expectation_string,
558 const char* expression,
559 int line) {
560 const bool success = expectation(lhs, rhs);
561 if (!success) {
562 CurrentTestExpectSimple(
563 expression,
564 MakeString<config::kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
565 ' ',
566 expectation_string,
567 ' ',
568 ConvertForPrint(rhs))
569 .c_str(),
570 line,
571 success);
572 }
573 return success;
574 }
575
576 // Skips the current test and dispatches an event for it.
577 ::pw::unit_test::internal::FailureMessageAdapter CurrentTestSkip(int line);
578
579 // Dispatches an event indicating the result of an expectation.
581 const char* expression,
582 const char* evaluated_expression,
583 int line,
584 bool success);
585
586 private:
587 // Convert char* to void* so that they are printed as pointers instead of
588 // strings in EXPECT_EQ and other macros. EXPECT_STREQ wraps its pointers in
589 // a CStringArg so its pointers are treated like C strings.
590 static constexpr const void* ConvertForPrint(const char* str) { return str; }
591
592 static constexpr const void* ConvertForPrint(char* str) { return str; }
593
594 static constexpr const char* ConvertForPrint(CStringArg value) {
595 return value.c_str;
596 }
597
598 template <typename T>
599 static constexpr T ConvertForPrint(T&& value) {
600 return std::forward<T>(value);
601 }
602
603 // If current_test_ will be first of its suite, call set_up_ts
604 void SetUpTestSuiteIfNeeded(SetUpTestSuiteFunc set_up_ts) const;
605
606 // If current_test_ was the last of its suite, call tear_down_ts
607 void TearDownTestSuiteIfNeeded(TearDownTestSuiteFunc tear_down_ts) const;
608
609 // Sets current_test_ and dispatches an event indicating that a test
610 // started.
611 void StartTest(const TestInfo& test);
612
613 // Dispatches event indicating that a test finished and clears
614 // current_test_.
615 void EndCurrentTest();
616
617 // Singleton instance of the framework class.
618 static Framework framework_;
619
620 // Linked list of all registered test cases. This is static as it tests are
621 // registered using static initialization.
622 static TestInfo* tests_;
623
624 // The current test case which is running.
625 const TestInfo* current_test_;
626
627 // Overall result of the current test case (pass/fail/skip).
628 TestResult current_result_;
629
630 // Overall result of the ongoing test run, which covers multiple tests.
631 RunTestsSummary run_tests_summary_;
632
633 // Program exit status returned by RunAllTests for GoogleTest compatibility.
634 int exit_status_;
635
636 // Handler to which to dispatch test events.
637 EventHandler* event_handler_;
638
639 span<std::string_view> test_suites_to_run_;
640
641 alignas(std::max_align_t) std::byte memory_pool_[config::kMemoryPoolSize];
642};
643
644// Information about a single test case, including a pointer to a function
645// which constructs and runs the test class. These are statically allocated
646// instead of the test classes, as test classes can be very large.
647class TestInfo {
648 public:
649 TestInfo(const char* const test_suite_name,
650 const char* const test_name,
651 const char* const file_name,
652 void (*run_func)(const TestInfo&))
653 : test_case_{
654 .suite_name = test_suite_name,
655 .test_name = test_name,
656 .file_name = file_name,
657 }, run_(run_func) {
658 Framework::Get().RegisterTest(this);
659 }
660
661 // The name of the suite to which the test case belongs, the name of the
662 // test case itself, and the path to the file in which the test case is
663 // located.
664 const TestCase& test_case() const { return test_case_; }
665
666 bool enabled() const;
667
668 void run() const { run_(*this); }
669
670 TestInfo* next() const { return next_; }
671 void set_next(TestInfo* next) { next_ = next; }
672
673 private:
674 TestCase test_case_;
675
676 // Function which runs the test case. Refers to Framework::CreateAndRunTest
677 // instantiated for the test case's class.
678 void (*run_)(const TestInfo&);
679
680 // TestInfo structs are registered with the test framework and stored as a
681 // linked list.
682 TestInfo* next_ = nullptr;
683};
684
685// Base class for all test cases or custom test fixtures.
686// Every unit test created using the TEST or TEST_F macro defines a class that
687// inherits from this (or a subclass of this).
688//
689// For example, given the following test definition:
690//
691// TEST(MyTest, SaysHello) {
692// ASSERT_STREQ(SayHello(), "Hello, world!");
693// }
694//
695// A new class is defined for the test, e.g. MyTest_SaysHello_Test. This class
696// inherits from the Test class and implements its PigweedTestBody function
697// with the block provided to the TEST macro.
698class Test {
699 public:
700 Test(const Test&) = delete;
701 Test& operator=(const Test&) = delete;
702
703 virtual ~Test() = default;
704
705 static void SetUpTestSuite() {}
706 static void TearDownTestSuite() {}
707
708 static bool HasFailure() { return Framework::Get().HasFailure(); }
709
710 // Runs the unit test.
711 void PigweedTestRun() {
712 SetUp();
713 if (!HasFailure() && !Framework::Get().IsSkipped()) {
714 PigweedTestBody();
715 }
716 TearDown();
717 }
718
719 protected:
720 Test() = default;
721
722 // Called immediately before executing the test body.
723 //
724 // Setup and cleanup can typically be done in the test fixture's constructor
725 // and destructor, but there are cases where SetUp/TearDown must be used
726 // instead. See the Google Test documentation for more information.
727 virtual void SetUp() {}
728
729 // Called immediately after executing the test body.
730 virtual void TearDown() {}
731
732 private:
733 friend class internal::Framework;
734
735 // The user-provided body of the test case. Populated by the TEST macro.
736 virtual void PigweedTestBody() = 0;
737};
738
739// Checks that a test suite name is valid.
740constexpr bool HasNoUnderscores(const char* suite) {
741 const char* disabled_prefix = "DISABLED_";
742
743 for (; *suite != '\0'; ++suite) {
744 if (*suite == *disabled_prefix) {
745 disabled_prefix += 1;
746 } else {
747 disabled_prefix = "";
748 if (*suite == '_') {
749 return false;
750 }
751 }
752 }
753 return true;
754}
755
756} // namespace internal
757
758inline void SetTestSuitesToRun(span<std::string_view> test_suites) {
759 internal::Framework::Get().SetTestSuitesToRun(test_suites);
760}
761
762} // namespace unit_test
763} // namespace pw
764
765inline int RUN_ALL_TESTS() {
766 return ::pw::unit_test::internal::Framework::Get().RunAllTests();
767}
768
769#define _PW_TEST(test_suite_name, test_name, parent_class) \
770 static_assert(sizeof(#test_suite_name) > 1, \
771 "The test suite name must not be empty"); \
772 static_assert(::pw::unit_test::internal::HasNoUnderscores(#test_suite_name), \
773 "The test suite name (" #test_suite_name \
774 ") cannot contain underscores"); \
775 static_assert(sizeof(#test_name) > 1, "The test name must not be empty"); \
776 \
777 _PW_TEST_CLASS(test_suite_name, \
778 test_name, \
779 test_suite_name##_##test_name##_Test, \
780 parent_class)
781
782#define _PW_TEST_CLASS(suite, name, class_name, parent_class) \
783 class class_name final : public parent_class { \
784 private: \
785 void PigweedTestBody() override; \
786 }; \
787 \
788 extern "C" { \
789 \
790 /* Silence ASAN to avoid errors in the initialization order checker */ \
791 /* caused by the intentional use of dynamic initializers which modify */ \
792 /* other globals */ \
793 PW_NO_SANITIZE("address") \
794 /* Declare the TestInfo as non-const since const variables do not work */ \
795 /* with the PW_UNIT_TEST_LINK_FILE_CONTAINING_TEST macro. */ \
796 /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ \
797 ::pw::unit_test::internal::TestInfo _pw_unit_test_Info_##suite##_##name( \
798 #suite, \
799 #name, \
800 __FILE__, \
801 ::pw::unit_test::internal::Framework::CreateAndRunTest<class_name>); \
802 \
803 } /* extern "C" */ \
804 \
805 void class_name::PigweedTestBody()
806
807#define _PW_TEST_ASSERT(expectation) \
808 if (!(expectation)) \
809 return ::pw::unit_test::internal::ReturnHelper() = \
810 ::pw::unit_test::internal::FailureMessageAdapter()
811
812#define _PW_TEST_EXPECT(expectation) \
813 if (!(expectation)) \
814 ::pw::unit_test::internal::FailureMessageAdapter()
815
816#define _PW_TEST_BOOL(expr, value) \
817 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
818 [](bool _pw_lhs, bool _pw_rhs) { return _pw_lhs == _pw_rhs; }, \
819 static_cast<bool>(expr), \
820 value, \
821 "is", \
822 #expr " is " #value, \
823 __LINE__)
824
825#define _PW_TEST_OP(lhs, rhs, op) \
826 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
827 [](const auto& _pw_lhs, const auto& _pw_rhs) { \
828 return _pw_lhs op _pw_rhs; \
829 }, \
830 (lhs), \
831 (rhs), \
832 #op, \
833 #lhs " " #op " " #rhs, \
834 __LINE__)
835
836#define _PW_TEST_NEAR(lhs, rhs, epsilon) \
837 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectWithEpsilon( \
838 [](const auto& _pw_lhs, const auto& _pw_rhs, const auto& _pw_epsilon) { \
839 return std::abs(_pw_lhs - _pw_rhs) <= _pw_epsilon; \
840 }, \
841 (lhs), \
842 (rhs), \
843 (epsilon), \
844 #lhs " within " #epsilon " of " #rhs, \
845 __LINE__)
846
847#define _PW_TEST_C_STR(lhs, rhs, op) \
848 ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
849 [](const auto& _pw_lhs, const auto& _pw_rhs) { \
850 auto cmp = [](const char* l, const char* r) -> int { \
851 if (!l || !r) { \
852 return l != r; \
853 } \
854 return std::strcmp(l, r); \
855 }; \
856 return cmp(_pw_lhs.c_str, _pw_rhs.c_str) op 0; \
857 }, \
858 ::pw::unit_test::internal::CStringArg{lhs}, \
859 ::pw::unit_test::internal::CStringArg{rhs}, \
860 #op, \
861 #lhs " " #op " " #rhs, \
862 __LINE__)
863
864// Checks that test suite names between TEST and TEST_F declarations are unique.
865// This works by declaring a function named for the test suite. The function
866// takes no arguments but is declared with different return types in the TEST
867// and TEST_F macros. If a TEST and TEST_F use the same test suite name, the
868// function declarations conflict, resulting in a compilation error.
869//
870// This catches most conflicts, but a runtime check is ultimately needed since
871// tests may be declared in different translation units.
872#if !defined(__clang__) && !defined(__GNUC___) && __GNUC__ <= 8
873// For some reason GCC8 is unable to ignore -Wredundant-decls here.
874#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite)
875#else // All other compilers.
876#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite) \
877 PW_MODIFY_DIAGNOSTICS_PUSH(); \
878 PW_MODIFY_DIAGNOSTIC(ignored, "-Wredundant-decls"); \
879 extern "C" return_type /* use extern "C" to escape namespacing */ \
880 PwUnitTestSuiteNamesMustBeUniqueBetweenTESTandTEST_F_##test_suite(void); \
881 PW_MODIFY_DIAGNOSTICS_POP()
882#endif // GCC8 or older.
883
884namespace testing {
885
886// Alias Test as ::testing::Test for GoogleTest compatibility.
888
889// Provide a no-op init routine for GoogleTest compatibility.
890inline void InitGoogleTest(int*, char**) {}
891
892} // namespace testing
Definition: span_impl.h:235
Definition: event_handler.h:116
Definition: framework_backend.h:416
Definition: framework_backend.h:441
Definition: framework_backend.h:428
Definition: framework_backend.h:698
Definition: framework_backend.h:647
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
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:53
Definition: event_handler.h:28
Definition: framework_backend.h:402