Pigweed
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
15// The Pigweed unit test framework requires C++17 to use its full functionality.
16#pragma once
17
18// IWYU pragma: private, include "pw_unit_test/framework.h"
19
20#if defined(GTEST_TEST)
21#error \
22 "GTEST_TEST is already defined. Make sure googletest headers are not " \
23 "included when using the pw_unit_test light backend."
24#endif // GTEST_TEST
25
26#include <cstddef>
27#include <cstdint>
28#include <cstring>
29#include <new>
30
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"
38
39#if PW_CXX_STANDARD_IS_SUPPORTED(17)
40#include <string_view>
41
43#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
44
47#define GTEST_TEST(test_suite_name, test_name) \
48 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(void /* TEST */, test_suite_name); \
49 _PW_TEST(test_suite_name, test_name, ::pw::unit_test::internal::Test)
50
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)
62#endif // !GTEST_DONT_DEFINE_TEST
63
69#define TEST_F(test_fixture, test_name) \
70 _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(int /* TEST_F */, test_fixture); \
71 _PW_TEST(test_fixture, test_name, test_fixture)
72
82#define FRIEND_TEST(test_suite_name, test_name) \
83 friend class test_suite_name##_##test_name##_Test
84
89#define EXPECT_TRUE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, true))
90
95#define EXPECT_FALSE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, false))
96
110#define EXPECT_EQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, ==))
111
121
124#define EXPECT_NE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, !=))
125
131#define EXPECT_GT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >))
132
138#define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=))
139
145#define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <))
146
152#define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=))
153
161#define EXPECT_NEAR(lhs, rhs, epsilon) \
162 _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon))
163
170#define EXPECT_FLOAT_EQ(lhs, rhs) \
171 _PW_TEST_EXPECT( \
172 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
173
180#define EXPECT_DOUBLE_EQ(lhs, rhs) \
181 _PW_TEST_EXPECT( \
182 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
183
189#define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==))
190
196#define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=))
197
200#define ASSERT_TRUE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, true))
201
204#define ASSERT_FALSE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, false))
205
208#define ASSERT_EQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, ==))
209
212#define ASSERT_NE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, !=))
213
216#define ASSERT_GT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >))
217
220#define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=))
221
224#define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <))
225
228#define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=))
229
232#define ASSERT_NEAR(lhs, rhs, epsilon) \
233 _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon))
234
237#define ASSERT_FLOAT_EQ(lhs, rhs) \
238 _PW_TEST_ASSERT( \
239 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
240
243#define ASSERT_DOUBLE_EQ(lhs, rhs) \
244 _PW_TEST_ASSERT( \
245 _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
246
249#define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==))
250
253#define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=))
254
257#define ADD_FAILURE() \
258 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
259 "(line is not executed)", "(line was executed)", __LINE__, false); \
260 _PW_UNIT_TEST_LOG
261
265#define GTEST_FAIL() return ADD_FAILURE()
266
270#define GTEST_SKIP() \
271 ::pw::unit_test::internal::Framework::Get().CurrentTestSkip(__LINE__); \
272 return _PW_UNIT_TEST_LOG
273
279#if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
280#define FAIL() GTEST_FAIL()
281#endif // !GTEST_DONT_DEFINE_FAIL
282
286#define GTEST_SUCCEED() \
287 ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
288 "(success)", "(success)", __LINE__, true); \
289 _PW_UNIT_TEST_LOG
290
297#if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
298#define SUCCEED() GTEST_SUCCEED()
299#endif // !GTEST_DONT_DEFINE_SUCCEED
300
309#define RUN_ALL_TESTS() \
310 ::pw::unit_test::internal::Framework::Get().RunAllTests()
311
314#define GTEST_HAS_DEATH_TEST 0
315
318#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
319 if (0) { \
320 static_cast<void>(statement); \
321 static_cast<void>(regex); \
322 } \
323 static_assert(true, "Macros must be terminated with a semicolon")
324
327#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
328 EXPECT_DEATH_IF_SUPPORTED(statement, regex)
329
330namespace pw {
331
332#if PW_CXX_STANDARD_IS_SUPPORTED(17)
333
334namespace string {
335
336// This function is used to print unknown types that are used in EXPECT or
337// ASSERT statements in tests.
338//
339// You can add support for displaying custom types by defining a ToString
340// template specialization. For example:
341//
342// namespace pw {
343//
344// template <>
345// StatusWithSize ToString<MyType>(const MyType& value,
346// span<char> buffer) {
347// return string::Format("<MyType|%d>", value.id);
348// }
349//
350// } // namespace pw
351//
352// See the documentation in pw_string/string_builder.h for more information.
353template <typename T>
354StatusWithSize UnknownTypeToString(const T& value, span<char> buffer) {
355 StringBuilder sb(buffer);
356 sb << '<' << sizeof(value) << "-byte object at 0x" << &value;
357
358 // How many bytes of the object to print.
359 //
360 // WARNING: Printing the contents of an object may be undefined behavior!
361 // Accessing unintialized memory is undefined behavior, and objects sometimes
362 // contiain uninitialized regions, such as padding bytes or unalloacted
363 // storage (e.g. std::optional). kPrintMaybeUnintializedBytes MUST stay at 0,
364 // except when changed locally to help with debugging.
365 constexpr size_t kPrintMaybeUnintializedBytes = 0;
366
367 constexpr size_t kBytesToPrint =
368 std::min(sizeof(value), kPrintMaybeUnintializedBytes);
369
370 if (kBytesToPrint != 0u) {
371 sb << " |";
372
373 // reinterpret_cast to std::byte is permitted by C++'s type aliasing rules.
374 const std::byte* bytes = reinterpret_cast<const std::byte*>(&value);
375
376 for (size_t i = 0; i < kBytesToPrint; ++i) {
377 sb << ' ' << bytes[i];
378 }
379
380 // If there's just one more byte, output it. Otherwise, output ellipsis.
381 if (sizeof(value) == kBytesToPrint + 1) {
382 sb << ' ' << bytes[sizeof(value) - 1];
383 } else if (sizeof(value) > kBytesToPrint) {
384 sb << " …";
385 }
386 }
387
388 sb << '>';
389 return sb.status_with_size();
390}
391
392} // namespace string
393
394#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
395
396namespace unit_test {
397namespace internal {
398
399class Test;
400class TestInfo;
401
402// Types of SetUpTestSuite() and TearDownTestSuite() functions.
403using SetUpTestSuiteFunc = void (*)();
404using TearDownTestSuiteFunc = void (*)();
405
406// Used to tag arguments to EXPECT_STREQ/EXPECT_STRNE so they are treated like C
407// strings rather than pointers.
409 const char* const c_str;
410};
411
412constexpr size_t MaxPaddingNeededToRaiseAlignment(size_t current_align,
413 size_t new_align) {
414 if (new_align < current_align) {
415 return 0;
416 }
417 return new_align - current_align;
418}
419
420// Singleton test framework class responsible for managing and running test
421// cases. This implementation is internal to Pigweed test; free functions
422// wrapping its functionality are exposed as the public interface.
424 public:
425 constexpr Framework()
426 : current_test_(nullptr),
427 current_result_(TestResult::kSuccess),
428 run_tests_summary_{.passed_tests = 0,
429 .failed_tests = 0,
430 .skipped_tests = 0,
431 .disabled_tests = 0},
432 exit_status_(0),
433 event_handler_(nullptr),
434 memory_pool_() {}
435
436 static Framework& Get() { return framework_; }
437
438 // Registers a single test case with the framework. The framework owns the
439 // registered unit test. Called during static initialization.
440 void RegisterTest(TestInfo* test) const;
441
442 // Sets the handler to which the framework dispatches test events. During a
443 // test run, the framework owns the event handler.
444 inline void RegisterEventHandler(EventHandler* event_handler) {
445 event_handler_ = event_handler;
446 }
447
448 // Runs all registered test cases, returning a status of 0 if all succeeded or
449 // nonzero if there were any failures. Test events that occur during the run
450 // are sent to the registered event handler, if any.
451 int RunAllTests();
452
453#if PW_CXX_STANDARD_IS_SUPPORTED(17)
454 // Only run test suites whose names are included in the provided list during
455 // the next test run. This is C++17 only; older versions of C++ will run all
456 // non-disabled tests.
457 void SetTestSuitesToRun(span<std::string_view> test_suites) {
458 test_suites_to_run_ = test_suites;
459 }
460#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
461
462 bool ShouldRunTest(const TestInfo& test_info) const;
463
464 // Whether the current test is skipped.
465 bool IsSkipped() const { return current_result_ == TestResult::kSkipped; }
466
467 // Whether the current test has failed.
468 bool HasFailure() const { return current_result_ == TestResult::kFailure; }
469
470 // Constructs an instance of a unit test class and runs the test.
471 //
472 // Tests are constructed within a static memory pool at run time instead of
473 // being statically allocated to avoid blowing up the size of the test binary
474 // in cases where users have large test fixtures (e.g. containing buffers)
475 // reused many times. Instead, only a small, fixed-size TestInfo struct is
476 // statically allocated per test case, with a run() function that references
477 // this method instantiated for its test class.
478 template <typename TestInstance>
479 static void CreateAndRunTest(const TestInfo& test_info) {
480 static_assert(
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 "
487 "test fixture.");
488
489 Framework& framework = Get();
490 framework.StartTest(test_info);
491
492 // Reset the memory pool to a marker value to help detect use of
493 // uninitialized memory.
494 std::memset(&framework.memory_pool_, 0xa5, sizeof(framework.memory_pool_));
495
496 framework.SetUpTestSuiteIfNeeded(TestInstance::SetUpTestSuite);
497
498 // Construct the test object within the static memory pool. The StartTest
499 // function has already been called by the TestInfo at this point.
500 void* aligned_pool =
501 AlignUp(&framework.memory_pool_, alignof(TestInstance));
502 TestInstance* test_instance = new (aligned_pool) TestInstance();
503 test_instance->PigweedTestRun();
504
505 // Manually call the destructor as it is not called automatically for
506 // objects constructed using placement new.
507 test_instance->~TestInstance();
508
509 framework.TearDownTestSuiteIfNeeded(TestInstance::TearDownTestSuite);
510
511 framework.EndCurrentTest();
512 }
513
514 template <typename Expectation, typename Lhs, typename Rhs, typename Epsilon>
515 bool CurrentTestExpect(Expectation expectation,
516 const Lhs& lhs,
517 const Rhs& rhs,
518 const Epsilon& epsilon,
519 const char* expression,
520 int line) {
521 // Size of the buffer into which to write the string with the evaluated
522 // version of the arguments. This buffer is allocated on the unit test's
523 // stack, so it shouldn't be too large.
524 // TODO(hepler): Make this configurable.
525 [[maybe_unused]] constexpr size_t kExpectationBufferSizeBytes = 192;
526
527 const bool success = expectation(lhs, rhs, epsilon);
528 CurrentTestExpectSimple(
529 expression,
530#if PW_CXX_STANDARD_IS_SUPPORTED(17)
531 MakeString<kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
532 " within ",
533 ConvertForPrint(epsilon),
534 " of ",
535 ConvertForPrint(rhs))
536 .c_str(),
537#else
538 "(evaluation requires C++17)",
539#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
540 line,
541 success);
542 return success;
543 }
544
545 // Runs an expectation function for the currently active test case.
546 template <typename Expectation, typename Lhs, typename Rhs>
547 bool CurrentTestExpect(Expectation expectation,
548 const Lhs& lhs,
549 const Rhs& rhs,
550 [[maybe_unused]] const char* expectation_string,
551 const char* expression,
552 int line) {
553 // Size of the buffer into which to write the string with the evaluated
554 // version of the arguments. This buffer is allocated on the unit test's
555 // stack, so it shouldn't be too large.
556 // TODO(hepler): Make this configurable.
557 [[maybe_unused]] constexpr size_t kExpectationBufferSizeBytes = 192;
558
559 const bool success = expectation(lhs, rhs);
560 CurrentTestExpectSimple(
561 expression,
562#if PW_CXX_STANDARD_IS_SUPPORTED(17)
563 MakeString<kExpectationBufferSizeBytes>(ConvertForPrint(lhs),
564 ' ',
565 expectation_string,
566 ' ',
567 ConvertForPrint(rhs))
568 .c_str(),
569#else
570 "(evaluation requires C++17)",
571#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
572 line,
573 success);
574 return success;
575 }
576
577 // Skips the current test and dispatches an event for it.
578 void CurrentTestSkip(int line);
579
580 // Dispatches an event indicating the result of an expectation.
581 void CurrentTestExpectSimple(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 a
589 // 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 started.
610 void StartTest(const TestInfo& test);
611
612 // Dispatches event indicating that a test finished and clears current_test_.
613 void EndCurrentTest();
614
615 // Singleton instance of the framework class.
616 static Framework framework_;
617
618 // Linked list of all registered test cases. This is static as it tests are
619 // registered using static initialization.
620 static TestInfo* tests_;
621
622 // The current test case which is running.
623 const TestInfo* current_test_;
624
625 // Overall result of the current test case (pass/fail/skip).
626 TestResult current_result_;
627
628 // Overall result of the ongoing test run, which covers multiple tests.
629 RunTestsSummary run_tests_summary_;
630
631 // Program exit status returned by RunAllTests for GoogleTest compatibility.
632 int exit_status_;
633
634 // Handler to which to dispatch test events.
635 EventHandler* event_handler_;
636
637#if PW_CXX_STANDARD_IS_SUPPORTED(17)
638 span<std::string_view> test_suites_to_run_;
639#else
640 span<const char*> test_suites_to_run_; // Always empty in C++14.
641#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
642
643 alignas(std::max_align_t) std::byte memory_pool_[config::kMemoryPoolSize];
644};
645
646// Information about a single test case, including a pointer to a function which
647// constructs and runs the test class. These are statically allocated instead of
648// the test classes, as test classes can be very large.
649class TestInfo {
650 public:
651 TestInfo(const char* const test_suite_name,
652 const char* const test_name,
653 const char* const file_name,
654 void (*run_func)(const TestInfo&))
655 : test_case_{
656 .suite_name = test_suite_name,
657 .test_name = test_name,
658 .file_name = file_name,
659 }, run_(run_func) {
660 Framework::Get().RegisterTest(this);
661 }
662
663 // The name of the suite to which the test case belongs, the name of the test
664 // case itself, and the path to the file in which the test case is located.
665 const TestCase& test_case() const { return test_case_; }
666
667 bool enabled() const;
668
669 void run() const { run_(*this); }
670
671 TestInfo* next() const { return next_; }
672 void set_next(TestInfo* next) { next_ = next; }
673
674 private:
675 TestCase test_case_;
676
677 // Function which runs the test case. Refers to Framework::CreateAndRunTest
678 // instantiated for the test case's class.
679 void (*run_)(const TestInfo&);
680
681 // TestInfo structs are registered with the test framework and stored as a
682 // linked list.
683 TestInfo* next_ = nullptr;
684};
685
686// Base class for all test cases or custom test fixtures.
687// Every unit test created using the TEST or TEST_F macro defines a class that
688// inherits from this (or a subclass of this).
689//
690// For example, given the following test definition:
691//
692// TEST(MyTest, SaysHello) {
693// ASSERT_STREQ(SayHello(), "Hello, world!");
694// }
695//
696// A new class is defined for the test, e.g. MyTest_SaysHello_Test. This class
697// inherits from the Test class and implements its PigweedTestBody function with
698// the block provided to the TEST macro.
699class Test {
700 public:
701 Test(const Test&) = delete;
702 Test& operator=(const Test&) = delete;
703
704 virtual ~Test() = default;
705
706 static void SetUpTestSuite() {}
707 static void TearDownTestSuite() {}
708
709 static bool HasFailure() { return Framework::Get().HasFailure(); }
710
711 // Runs the unit test.
712 void PigweedTestRun() {
713 SetUp();
714 // TODO(deymo): Skip the test body if there's a fatal error in SetUp().
715 if (!Framework::Get().IsSkipped()) {
716 PigweedTestBody();
717 }
718 TearDown();
719 }
720
721 protected:
722 Test() = default;
723
724 // Called immediately before executing the test body.
725 //
726 // Setup and cleanup can typically be done in the test fixture's constructor
727 // and destructor, but there are cases where SetUp/TearDown must be used
728 // instead. See the Google Test documentation for more information.
729 virtual void SetUp() {}
730
731 // Called immediately after executing the test body.
732 virtual void TearDown() {}
733
734 private:
735 friend class internal::Framework;
736
737 // The user-provided body of the test case. Populated by the TEST macro.
738 virtual void PigweedTestBody() = 0;
739};
740
741// Checks that a test suite name is valid.
742constexpr bool HasNoUnderscores(const char* suite) {
743 const char* disabled_prefix = "DISABLED_";
744
745 for (; *suite != '\0'; ++suite) {
746 if (*suite == *disabled_prefix) {
747 disabled_prefix += 1;
748 } else {
749 disabled_prefix = "";
750 if (*suite == '_') {
751 return false;
752 }
753 }
754 }
755 return true;
756}
757
758// GoogleTest supports stream-style messages, but pw_unit_test does not. This
759// class accepts and ignores C++ <<-style logs. This could be replaced with
760// pw_log/glog_adapter.h.
762 public:
763 constexpr IgnoreLogs() = default;
764
765 template <typename T>
766 constexpr const IgnoreLogs& operator<<(const T&) const {
767 return *this;
768 }
769};
770
771// Used to ignore a stream-style message in an assert, which returns. This uses
772// a similar approach as upstream GoogleTest, but drops any messages.
774 public:
775 constexpr ReturnHelper() = default;
776
777 // Return void so that assigning to ReturnHelper converts the log expression
778 // to void without blocking the stream-style log with a closing parenthesis.
779 // NOLINTNEXTLINE(misc-unconventional-assign-operator)
780 constexpr void operator=(const IgnoreLogs&) const {}
781};
782
783#define _PW_UNIT_TEST_LOG \
784 ::pw::unit_test::internal::ReturnHelper() = \
785 ::pw::unit_test::internal::IgnoreLogs()
786
787} // namespace internal
788
789#if PW_CXX_STANDARD_IS_SUPPORTED(17)
790inline void SetTestSuitesToRun(span<std::string_view> test_suites) {
791 internal::Framework::Get().SetTestSuitesToRun(test_suites);
792}
793#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
794
795} // namespace unit_test
796} // namespace pw
797
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"); \
805 \
806 _PW_TEST_CLASS(test_suite_name, \
807 test_name, \
808 test_suite_name##_##test_name##_Test, \
809 parent_class)
810
811#define _PW_TEST_CLASS(suite, name, class_name, parent_class) \
812 class class_name final : public parent_class { \
813 private: \
814 void PigweedTestBody() override; \
815 }; \
816 \
817 extern "C" { \
818 \
819 /* Silence ASAN to avoid errors in the initialization order checker */ \
820 /* caused by the intentional use of dynamic initializers which modify */ \
821 /* other globals */ \
822 PW_NO_SANITIZE("address") \
823 /* Declare the TestInfo as non-const since const variables do not work */ \
824 /* with the PW_UNIT_TEST_LINK_FILE_CONTAINING_TEST macro. */ \
825 /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ \
826 ::pw::unit_test::internal::TestInfo _pw_unit_test_Info_##suite##_##name( \
827 #suite, \
828 #name, \
829 __FILE__, \
830 ::pw::unit_test::internal::Framework::CreateAndRunTest<class_name>); \
831 \
832 } /* extern "C" */ \
833 \
834 void class_name::PigweedTestBody()
835
836#define _PW_TEST_ASSERT(expectation) \
837 if (!(expectation)) \
838 return _PW_UNIT_TEST_LOG
839
840#define _PW_TEST_EXPECT(expectation) \
841 if (!(expectation)) \
842 _PW_UNIT_TEST_LOG
843
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), \
848 value, \
849 "is", \
850 #expr " is " #value, \
851 __LINE__)
852
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; \
857 }, \
858 (lhs), \
859 (rhs), \
860 #op, \
861 #lhs " " #op " " #rhs, \
862 __LINE__)
863
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; \
868 }, \
869 (lhs), \
870 (rhs), \
871 (epsilon), \
872 #lhs " within " #epsilon " of " #rhs, \
873 __LINE__)
874
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 { \
879 if (!l || !r) { \
880 return l != r; \
881 } \
882 return std::strcmp(l, r); \
883 }; \
884 return cmp(_pw_lhs.c_str, _pw_rhs.c_str) op 0; \
885 }, \
886 ::pw::unit_test::internal::CStringArg{lhs}, \
887 ::pw::unit_test::internal::CStringArg{rhs}, \
888 #op, \
889 #lhs " " #op " " #rhs, \
890 __LINE__)
891
892// Checks that test suite names between TEST and TEST_F declarations are unique.
893// This works by declaring a function named for the test suite. The function
894// takes no arguments but is declared with different return types in the TEST
895// and TEST_F macros. If a TEST and TEST_F use the same test suite name, the
896// function declarations conflict, resulting in a compilation error.
897//
898// This catches most conflicts, but a runtime check is ultimately needed since
899// tests may be declared in different translation units.
900#if !defined(__clang__) && !defined(__GNUC___) && __GNUC__ <= 8
901// For some reason GCC8 is unable to ignore -Wredundant-decls here.
902#define _PW_TEST_SUITE_NAMES_MUST_BE_UNIQUE(return_type, test_suite)
903#else // All other compilers.
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 /* use extern "C" to escape namespacing */ \
908 PwUnitTestSuiteNamesMustBeUniqueBetweenTESTandTEST_F_##test_suite(void); \
909 PW_MODIFY_DIAGNOSTICS_POP()
910#endif // GCC8 or older.
911
912namespace testing {
913
914// Alias Test as ::testing::Test for GoogleTest compatibility.
916
917// Provide a no-op init routine for GoogleTest compatibility.
918inline void InitGoogleTest(int*, char**) {}
919
920} // namespace testing
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