Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_unit_test / public / pw_unit_test / framework.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 // In C++11, only the TEST, TEST_F, EXPECT_TRUE, EXPECT_FALSE, ASSERT_TRUE,
17 // ASSERT_FALSE, FAIL, and ADD_FAILURE macros may be used.
18 #pragma once
19
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstring>
23 #include <new>
24 #include <span>
25
26 #include "pw_polyfill/standard.h"
27 #include "pw_preprocessor/concat.h"
28 #include "pw_preprocessor/util.h"
29 #include "pw_unit_test/event_handler.h"
30
31 #if PW_CXX_STANDARD_IS_SUPPORTED(17)
32 #include "pw_string/string_builder.h"
33 #endif  // PW_CXX_STANDARD_IS_SUPPORTED(17)
34
35 #define PW_TEST(test_suite_name, test_name) \
36   _PW_TEST(test_suite_name, test_name, ::pw::unit_test::Test)
37
38 // TEST() is a pretty generic macro name which could conflict with other code.
39 // If GTEST_DONT_DEFINE_TEST is set, don't alias PW_TEST to TEST.
40 #if !(defined(GTEST_DONT_DEFINE_TEST) && GTEST_DONT_DEFINE_TEST)
41 #define TEST PW_TEST
42 #endif  // !GTEST_DONT_DEFINE_TEST
43
44 #define TEST_F(test_fixture, test_name) \
45   _PW_TEST(test_fixture, test_name, test_fixture)
46
47 #define EXPECT_TRUE(expr) _PW_EXPECT_BOOL(expr, true)
48 #define EXPECT_FALSE(expr) _PW_EXPECT_BOOL(expr, false)
49 #define EXPECT_EQ(lhs, rhs) _PW_TEST_OP(_PW_TEST_EXPECT, lhs, rhs, ==)
50 #define EXPECT_NE(lhs, rhs) _PW_TEST_OP(_PW_TEST_EXPECT, lhs, rhs, !=)
51 #define EXPECT_GT(lhs, rhs) _PW_TEST_OP(_PW_TEST_EXPECT, lhs, rhs, >)
52 #define EXPECT_GE(lhs, rhs) _PW_TEST_OP(_PW_TEST_EXPECT, lhs, rhs, >=)
53 #define EXPECT_LT(lhs, rhs) _PW_TEST_OP(_PW_TEST_EXPECT, lhs, rhs, <)
54 #define EXPECT_LE(lhs, rhs) _PW_TEST_OP(_PW_TEST_EXPECT, lhs, rhs, <=)
55 #define EXPECT_STREQ(lhs, rhs) _PW_TEST_STREQ(_PW_TEST_EXPECT, lhs, rhs)
56 #define EXPECT_STRNE(lhs, rhs) _PW_TEST_STRNE(_PW_TEST_EXPECT, lhs, rhs)
57
58 #define ASSERT_TRUE(expr) _PW_ASSERT_BOOL(expr, true)
59 #define ASSERT_FALSE(expr) _PW_ASSERT_BOOL(expr, false)
60 #define ASSERT_EQ(lhs, rhs) _PW_TEST_OP(_PW_TEST_ASSERT, lhs, rhs, ==)
61 #define ASSERT_NE(lhs, rhs) _PW_TEST_OP(_PW_TEST_ASSERT, lhs, rhs, !=)
62 #define ASSERT_GT(lhs, rhs) _PW_TEST_OP(_PW_TEST_ASSERT, lhs, rhs, >)
63 #define ASSERT_GE(lhs, rhs) _PW_TEST_OP(_PW_TEST_ASSERT, lhs, rhs, >=)
64 #define ASSERT_LT(lhs, rhs) _PW_TEST_OP(_PW_TEST_ASSERT, lhs, rhs, <)
65 #define ASSERT_LE(lhs, rhs) _PW_TEST_OP(_PW_TEST_ASSERT, lhs, rhs, <=)
66 #define ASSERT_STREQ(lhs, rhs) _PW_TEST_STREQ(_PW_TEST_ASSERT, lhs, rhs)
67 #define ASSERT_STRNE(lhs, rhs) _PW_TEST_STRNE(_PW_TEST_ASSERT, lhs, rhs)
68
69 // Generates a non-fatal failure with a generic message.
70 #define ADD_FAILURE() \
71   _PW_TEST_MESSAGE("(line is not executed)", "(line was executed)", false)
72
73 // Generates a fatal failure with a generic message.
74 #define GTEST_FAIL() return ADD_FAILURE()
75
76 // Define either macro to 1 to omit the definition of FAIL(), which is a
77 // generic name and clashes with some other libraries.
78 #if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
79 #define FAIL() GTEST_FAIL()
80 #endif  // !GTEST_DONT_DEFINE_FAIL
81
82 // Generates a success with a generic message.
83 #define GTEST_SUCCEED() _PW_TEST_MESSAGE("(success)", "(success)", true)
84
85 // Define either macro to 1 to omit the definition of SUCCEED(), which
86 // is a generic name and clashes with some other libraries.
87 #if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
88 #define SUCCEED() GTEST_SUCCEED()
89 #endif  // !GTEST_DONT_DEFINE_SUCCEED
90
91 // pw_unit_test framework entry point. Runs every registered test case and
92 // dispatches the results through the event handler. Returns a status of zero
93 // if all tests passed, or nonzero if there were any failures.
94 // This is compatible with Googletest.
95 //
96 // In order to receive test output, an event handler must be registered before
97 // this is called:
98 //
99 //   int main() {
100 //     MyEventHandler handler;
101 //     pw::unit_test::RegisterEventHandler(&handler);
102 //     return RUN_ALL_TESTS();
103 //   }
104 //
105 #define RUN_ALL_TESTS() \
106   ::pw::unit_test::internal::Framework::Get().RunAllTests()
107
108 namespace pw {
109
110 #if PW_CXX_STANDARD_IS_SUPPORTED(17)
111
112 namespace string {
113
114 // This function is used to print unknown types that are used in EXPECT or
115 // ASSERT statements in tests.
116 //
117 // You can add support for displaying custom types by defining a ToString
118 // template specialization. For example:
119 //
120 //   namespace pw {
121 //
122 //   template <>
123 //   StatusWithSize ToString<MyType>(const MyType& value,
124 //                                   std::span<char> buffer) {
125 //     return string::Format("<MyType|%d>", value.id);
126 //   }
127 //
128 //   }  // namespace pw
129 //
130 // See the documentation in pw_string/string_builder.h for more information.
131 template <typename T>
132 StatusWithSize UnknownTypeToString(const T& value, std::span<char> buffer) {
133   StringBuilder sb(buffer);
134   sb << '<' << sizeof(value) << "-byte object at 0x" << &value << '>';
135   return sb.status_with_size();
136 }
137
138 }  // namespace string
139
140 #endif  // PW_CXX_STANDARD_IS_SUPPORTED(17)
141
142 namespace unit_test {
143
144 class Test;
145
146 namespace internal {
147
148 class TestInfo;
149
150 // Singleton test framework class responsible for managing and running test
151 // cases. This implementation is internal to Pigweed test; free functions
152 // wrapping its functionality are exposed as the public interface.
153 class Framework {
154  public:
155   constexpr Framework()
156       : current_test_(nullptr),
157         current_result_(TestResult::kSuccess),
158         run_tests_summary_{.passed_tests = 0, .failed_tests = 0},
159         exit_status_(0),
160         event_handler_(nullptr),
161         memory_pool_() {}
162
163   static Framework& Get() { return framework_; }
164
165   // Registers a single test case with the framework. The framework owns the
166   // registered unit test. Called during static initialization.
167   void RegisterTest(TestInfo* test);
168
169   // Sets the handler to which the framework dispatches test events. During a
170   // test run, the framework owns the event handler.
171   void RegisterEventHandler(EventHandler* event_handler) {
172     event_handler_ = event_handler;
173   }
174
175   // Runs all registered test cases, returning a status of 0 if all succeeded or
176   // nonzero if there were any failures. Test events that occur during the run
177   // are sent to the registered event handler, if any.
178   int RunAllTests();
179
180   // Constructs an instance of a unit test class and runs the test.
181   //
182   // Tests are constructed within a static memory pool at run time instead of
183   // being statically allocated to avoid blowing up the size of the test binary
184   // in cases where users have large test fixtures (e.g. containing buffers)
185   // reused many times. Instead, only a small, fixed-size TestInfo struct is
186   // statically allocated per test case, with a run() function that references
187   // this method instantiated for its test class.
188   template <typename TestInstance>
189   static void CreateAndRunTest(const TestInfo& test_info) {
190     // TODO(frolv): Update the assert message with the name of the config option
191     // for memory pool size once it is configurable.
192     static_assert(
193         sizeof(TestInstance) <= sizeof(memory_pool_),
194         "The test memory pool is too small for this test. Either increase "
195         "kTestMemoryPoolSizeBytes or decrease the size of your test fixture.");
196
197     Framework& framework = Get();
198     framework.StartTest(test_info);
199
200     // Reset the memory pool to a marker value to help detect use of
201     // uninitialized memory.
202     std::memset(&framework.memory_pool_, 0xa5, sizeof(framework.memory_pool_));
203
204     // Construct the test object within the static memory pool. The StartTest
205     // function has already been called by the TestInfo at this point.
206     TestInstance* test_instance = new (&framework.memory_pool_) TestInstance;
207     test_instance->PigweedTestRun();
208
209     // Manually call the destructor as it is not called automatically for
210     // objects constructed using placement new.
211     test_instance->~TestInstance();
212
213     framework.EndCurrentTest();
214   }
215
216   // Runs an expectation function for the currently active test case.
217   template <typename Expectation, typename Lhs, typename Rhs>
218   bool CurrentTestExpect(Expectation expectation,
219                          const Lhs& lhs,
220                          const Rhs& rhs,
221                          const char* expectation_string,
222                          const char* expression,
223                          int line) {
224     // Size of the buffer into which to write the string with the evaluated
225     // version of the arguments. This buffer is allocated on the unit test's
226     // stack, so it shouldn't be too large.
227     // TODO(hepler): Make this configurable.
228     constexpr size_t kExpectationBufferSizeBytes = 128;
229
230     bool result = expectation(lhs, rhs);
231     ExpectationResult(expression,
232 #if PW_CXX_STANDARD_IS_SUPPORTED(17)
233                       MakeString<kExpectationBufferSizeBytes>(
234                           lhs, ' ', expectation_string, ' ', rhs)
235                           .c_str(),
236 #else
237                       "(evaluation requires C++17)",
238 #endif  // PW_CXX_STANDARD_IS_SUPPORTED(17)
239                       line,
240                       result);
241
242     static_cast<void>(expectation_string);
243     static_cast<void>(kExpectationBufferSizeBytes);
244
245     return result;
246   }
247
248   // Dispatches an event indicating the result of an expectation.
249   void ExpectationResult(const char* expression,
250                          const char* evaluated_expression,
251                          int line,
252                          bool success);
253
254  private:
255   // Sets current_test_ and dispatches an event indicating that a test started.
256   void StartTest(const TestInfo& test);
257
258   // Dispatches event indicating that a test finished and clears current_test_.
259   void EndCurrentTest();
260
261   // Singleton instance of the framework class.
262   static Framework framework_;
263
264   // Linked list of all registered test cases. This is static as it tests are
265   // registered using static initialization.
266   static TestInfo* tests_;
267
268   // The current test case which is running.
269   const TestInfo* current_test_;
270
271   // Overall result of the current test case (pass/fail).
272   TestResult current_result_;
273
274   // Overall result of the ongoing test run, which covers multiple tests.
275   RunTestsSummary run_tests_summary_;
276
277   // Program exit status returned by RunAllTests for Googletest compatibility.
278   int exit_status_;
279
280   // Handler to which to dispatch test events.
281   EventHandler* event_handler_;
282
283   // Memory region in which to construct test case classes as they are run.
284   // TODO(frolv): Make the memory pool size configurable.
285   static constexpr size_t kTestMemoryPoolSizeBytes = 16384;
286   std::aligned_storage_t<kTestMemoryPoolSizeBytes, alignof(std::max_align_t)>
287       memory_pool_;
288 };
289
290 // Information about a single test case, including a pointer to a function which
291 // constructs and runs the test class. These are statically allocated instead of
292 // the test classes, as test classes can be very large.
293 class TestInfo {
294  public:
295   TestInfo(const char* const test_suite_name,
296            const char* const test_name,
297            const char* const file_name,
298            void (*run_func)(const TestInfo&))
299       : test_case_{
300         .suite_name = test_suite_name,
301         .test_name = test_name,
302         .file_name = file_name,
303        }, run_(run_func) {
304     Framework::Get().RegisterTest(this);
305   }
306
307   // The name of the suite to which the test case belongs, the name of the test
308   // case itself, and the path to the file in which the test case is located.
309   const TestCase& test_case() const { return test_case_; }
310
311   bool enabled() const;
312
313   void run() const { run_(*this); }
314
315   TestInfo* next() const { return next_; }
316   void set_next(TestInfo* next) { next_ = next; }
317
318  private:
319   TestCase test_case_;
320
321   // Function which runs the test case. Refers to Framework::CreateAndRunTest
322   // instantiated for the test case's class.
323   void (*run_)(const TestInfo&);
324
325   // TestInfo structs are registered with the test framework and stored as a
326   // linked list.
327   TestInfo* next_ = nullptr;
328 };
329
330 }  // namespace internal
331
332 // Base class for all test cases or custom test fixtures.
333 // Every unit test created using the TEST or TEST_F macro defines a class that
334 // inherits from this (or a subclass of this).
335 //
336 // For example, given the following test definition:
337 //
338 //   TEST(MyTest, SaysHello) {
339 //     ASSERT_STREQ(SayHello(), "Hello, world!");
340 //   }
341 //
342 // A new class is defined for the test, e.g. MyTest_SaysHello_Test. This class
343 // inherits from the Test class and implements its PigweedTestBody function with
344 // the block provided to the TEST macro.
345 class Test {
346  public:
347   Test(const Test&) = delete;
348   Test& operator=(const Test&) = delete;
349
350   virtual ~Test() = default;
351
352   // Runs the unit test.
353   void PigweedTestRun() {
354     SetUp();
355     PigweedTestBody();
356     TearDown();
357   }
358
359  protected:
360   Test() = default;
361
362   // Called immediately before executing the test body.
363   //
364   // Setup and cleanup can typically be done in the test fixture's constructor
365   // and destructor, but there are cases where SetUp/TearDown must be used
366   // instead. See the Google Test documentation for more information.
367   virtual void SetUp() {}
368
369   // Called immediately after executing the test body.
370   virtual void TearDown() {}
371
372  private:
373   friend class internal::Framework;
374
375   // The user-provided body of the test case. Populated by the TEST macro.
376   virtual void PigweedTestBody() = 0;
377 };
378
379 }  // namespace unit_test
380 }  // namespace pw
381
382 #define _PW_TEST_CLASS_NAME(test_suite_name, test_name) \
383   PW_CONCAT(test_suite_name, _, test_name, _Test)
384
385 #define _PW_TEST(test_suite_name, test_name, parent_class)              \
386   static_assert(sizeof(#test_suite_name) > 1,                           \
387                 "test_suite_name must not be empty");                   \
388   static_assert(sizeof(#test_name) > 1, "test_name must not be empty"); \
389                                                                         \
390   class _PW_TEST_CLASS_NAME(test_suite_name, test_name) final           \
391       : public parent_class {                                           \
392    private:                                                             \
393     void PigweedTestBody() override;                                    \
394                                                                         \
395     static ::pw::unit_test::internal::TestInfo test_info_;              \
396   };                                                                    \
397                                                                         \
398   ::pw::unit_test::internal::TestInfo                                   \
399       _PW_TEST_CLASS_NAME(test_suite_name, test_name)::test_info_(      \
400           #test_suite_name,                                             \
401           #test_name,                                                   \
402           __FILE__,                                                     \
403           ::pw::unit_test::internal::Framework::CreateAndRunTest<       \
404               _PW_TEST_CLASS_NAME(test_suite_name, test_name)>);        \
405                                                                         \
406   void _PW_TEST_CLASS_NAME(test_suite_name, test_name)::PigweedTestBody()
407
408 #define _PW_TEST_EXPECT(lhs, rhs, expectation, expectation_string) \
409   ::pw::unit_test::internal::Framework::Get().CurrentTestExpect(   \
410       expectation,                                                 \
411       (lhs),                                                       \
412       (rhs),                                                       \
413       expectation_string,                                          \
414       #lhs " " expectation_string " " #rhs,                        \
415       __LINE__)
416
417 #define _PW_TEST_ASSERT(lhs, rhs, expectation, expectation_string)     \
418   do {                                                                 \
419     if (!_PW_TEST_EXPECT(lhs, rhs, expectation, expectation_string)) { \
420       return;                                                          \
421     }                                                                  \
422   } while (0)
423
424 #define _PW_TEST_MESSAGE(expected, actual, success)              \
425   ::pw::unit_test::internal::Framework::Get().ExpectationResult( \
426       expected, actual, __LINE__, success)
427
428 #define _PW_TEST_OP(expect_or_assert, lhs, rhs, op)  \
429   expect_or_assert(                                  \
430       lhs,                                           \
431       rhs,                                           \
432       [](const auto& _pw_lhs, const auto& _pw_rhs) { \
433         return _pw_lhs op _pw_rhs;                   \
434       },                                             \
435       #op)
436
437 // Implement boolean expectations in a C++11-compatible way.
438 #define _PW_EXPECT_BOOL(expr, value)                             \
439   ::pw::unit_test::internal::Framework::Get().CurrentTestExpect( \
440       [](bool lhs, bool rhs) { return lhs == rhs; },             \
441       static_cast<bool>(expr),                                   \
442       value,                                                     \
443       "is",                                                      \
444       #expr " is " #value,                                       \
445       __LINE__)
446
447 #define _PW_ASSERT_BOOL(expr, value)     \
448   do {                                   \
449     if (!_PW_EXPECT_BOOL(expr, value)) { \
450       return;                            \
451     }                                    \
452   } while (0)
453
454 #define _PW_TEST_STREQ(expect_or_assert, lhs, rhs)   \
455   expect_or_assert(                                  \
456       lhs,                                           \
457       rhs,                                           \
458       [](const auto& _pw_lhs, const auto& _pw_rhs) { \
459         return std::strcmp(_pw_lhs, _pw_rhs) == 0;   \
460       },                                             \
461       "equals")
462
463 #define _PW_TEST_STRNE(expect_or_assert, lhs, rhs)   \
464   expect_or_assert(                                  \
465       lhs,                                           \
466       rhs,                                           \
467       [](const auto& _pw_lhs, const auto& _pw_rhs) { \
468         return std::strcmp(_pw_lhs, _pw_rhs) != 0;   \
469       },                                             \
470       "does not equal")
471
472 // Alias Test as ::testing::Test for Googletest compatibility.
473 namespace testing {
474 using Test = ::pw::unit_test::Test;
475 }  // namespace testing