• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
42 #include "pw_string/string_builder.h"
43 #endif  // PW_CXX_STANDARD_IS_SUPPORTED(17)
44 
45 /// @def GTEST_TEST
46 /// Alias for `TEST`.
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 
51 /// @def TEST
52 /// Defines a test given the suite name and test case name.
53 ///
54 /// If `TEST` is conflicting with other code, set `GTEST_DONT_DEFINE_TEST` to
55 /// 1 and use `GTEST_TEST` instead.
56 ///
57 /// @param[in] test_suite_name The name of the test suite or collection of
58 /// tests.
59 /// @param[in] test_name The name of the test case.
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 
64 /// @def TEST_F
65 /// Defines a test case using a test fixture.
66 ///
67 /// @param[in] test_fixture The name of the test fixture class to use.
68 /// @param[in] test_name The name of the test case.
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 
73 /// @def FRIEND_TEST
74 /// Defines a test case from a test suite as a friend class of an implementation
75 /// class.
76 ///
77 /// @warning Use of `FRIEND_TEST` is discouraged, because it induces coupling
78 /// between testing and implementation code. Consider this a last resort only.
79 ///
80 /// @param[in] test_suite_name The name of the test suite to befriend.
81 /// @param[in] test_name The name of the test case to befriend.
82 #define FRIEND_TEST(test_suite_name, test_name) \
83   friend class test_suite_name##_##test_name##_Test
84 
85 /// @def EXPECT_TRUE
86 /// Verifies that @p expr evaluates to true.
87 ///
88 /// @param[in] expr The expression to evaluate.
89 #define EXPECT_TRUE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, true))
90 
91 /// @def EXPECT_FALSE
92 /// Verifies that @p expr evaluates to false.
93 ///
94 /// @param[in] expr The expression to evaluate.
95 #define EXPECT_FALSE(expr) _PW_TEST_EXPECT(_PW_TEST_BOOL(expr, false))
96 
97 /// @def EXPECT_EQ
98 /// Verifies that `lhs == rhs`.
99 ///
100 /// Does pointer equality on pointers. If used on two C strings, `EXPECT_EQ`
101 /// tests if they are in the same memory location, not if they have the same
102 /// value. Use `EXPECT_STREQ` to compare C strings (e.g. `const char*`) by
103 /// value.
104 ///
105 /// When comparing a pointer to `NULL` use `EXPECT_EQ(ptr, nullptr)` instead of
106 /// `EXPECT_EQ(ptr, NULL)`.
107 ///
108 /// @param[in] lhs The left side of the equality comparison.
109 /// @param[in] rhs The right side of the equality comparison.
110 #define EXPECT_EQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, ==))
111 
112 /// @def EXPECT_NE
113 /// Verifies that `lhs != rhs`.
114 ///
115 /// Does pointer equality on pointers. If used on two C strings, it tests if
116 /// they are in different memory locations, not if they have different values.
117 /// Use `EXPECT_STRNE` to compare C strings (e.g. `const char*`) by value.
118 ///
119 /// When comparing a pointer to `NULL`, use `EXPECT_NE(ptr, nullptr)` instead
120 /// of `EXPECT_NE(ptr, NULL)`.
121 
122 /// @param[in] lhs The left side of the inequality comparison.
123 /// @param[in] rhs The right side of the inequality comparison.
124 #define EXPECT_NE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, !=))
125 
126 /// @def EXPECT_GT
127 /// Verifies that `lhs > rhs`.
128 ///
129 /// @param[in] lhs The left side of the comparison.
130 /// @param[in] rhs The right side of the comparison.
131 #define EXPECT_GT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >))
132 
133 /// @def EXPECT_GE
134 /// Verifies that `lhs >= rhs`.
135 ///
136 /// @param[in] lhs The left side of the comparison.
137 /// @param[in] rhs The right side of the comparison.
138 #define EXPECT_GE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, >=))
139 
140 /// @def EXPECT_LT
141 /// Verifies that `lhs < rhs`.
142 ///
143 /// @param[in] lhs The left side of the comparison.
144 /// @param[in] rhs The right side of the comparison.
145 #define EXPECT_LT(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <))
146 
147 /// @def EXPECT_LE
148 /// Verifies that `lhs <= rhs`.
149 ///
150 /// @param[in] lhs The left side of the comparison.
151 /// @param[in] rhs The right side of the comparison.
152 #define EXPECT_LE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_OP(lhs, rhs, <=))
153 
154 /// @def EXPECT_NEAR
155 /// Verifies that the difference between `lhs` and `rhs` does not exceed the
156 /// absolute error bound `epsilon`.
157 ///
158 /// @param[in] lhs The left side of the comparison.
159 /// @param[in] rhs The right side of the comparison.
160 /// @param[in] epsilon The maximum difference between `lhs` and `rhs`.
161 #define EXPECT_NEAR(lhs, rhs, epsilon) \
162   _PW_TEST_EXPECT(_PW_TEST_NEAR(lhs, rhs, epsilon))
163 
164 /// @def EXPECT_FLOAT_EQ
165 /// Verifies that the two float values `rhs` and `lhs` are approximately
166 /// equal, to within 4 units in the last place (ULPs) from each other.
167 ///
168 /// @param[in] lhs The left side of the equality comparison.
169 /// @param[in] rhs The right side of the equality comparison.
170 #define EXPECT_FLOAT_EQ(lhs, rhs) \
171   _PW_TEST_EXPECT(                \
172       _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
173 
174 /// @def EXPECT_DOUBLE_EQ
175 /// Verifies that the two double values `rhs` and `lhs` are approximately
176 /// equal, to within 4 units in the last place (ULPs) from each other.
177 ///
178 /// @param[in] lhs The left side of the equality comparison.
179 /// @param[in] rhs The right side of the equality comparison.
180 #define EXPECT_DOUBLE_EQ(lhs, rhs) \
181   _PW_TEST_EXPECT(                 \
182       _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
183 
184 /// @def EXPECT_STREQ
185 /// Verifies that the two C strings `lhs` and `rhs` have the same contents.
186 ///
187 /// @param[in] lhs The left side of the equality comparison.
188 /// @param[] rhs The right side of the equality comparison.
189 #define EXPECT_STREQ(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, ==))
190 
191 /// @def EXPECT_STRNE
192 /// Verifies that the two C strings `lhs` and `rhs` have different content.
193 ///
194 /// @param[in] lhs The left side of the inequality comparison.
195 /// @param[in] rhs The right side of the inequality comparison.
196 #define EXPECT_STRNE(lhs, rhs) _PW_TEST_EXPECT(_PW_TEST_C_STR(lhs, rhs, !=))
197 
198 /// @def ASSERT_TRUE
199 /// See `EXPECT_TRUE`.
200 #define ASSERT_TRUE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, true))
201 
202 /// @def ASSERT_FALSE
203 /// See `EXPECT_FALSE`.
204 #define ASSERT_FALSE(expr) _PW_TEST_ASSERT(_PW_TEST_BOOL(expr, false))
205 
206 /// @def ASSERT_EQ
207 /// See `EXPECT_EQ`.
208 #define ASSERT_EQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, ==))
209 
210 /// @def ASSERT_NE
211 /// See `EXPECT_NE`.
212 #define ASSERT_NE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, !=))
213 
214 /// @def ASSERT_GT
215 /// See `EXPECT_GT`.
216 #define ASSERT_GT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >))
217 
218 /// @def ASSERT_GE
219 /// See `EXPECT_GE`.
220 #define ASSERT_GE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, >=))
221 
222 /// @def ASSERT_LT
223 /// See `EXPECT_LT`.
224 #define ASSERT_LT(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <))
225 
226 /// @def ASSERT_LE
227 /// See `EXPECT_LE`.
228 #define ASSERT_LE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_OP(lhs, rhs, <=))
229 
230 /// @def ASSERT_NEAR
231 /// See `EXPECT_NEAR`.
232 #define ASSERT_NEAR(lhs, rhs, epsilon) \
233   _PW_TEST_ASSERT(_PW_TEST_NEAR(lhs, rhs, epsilon))
234 
235 /// @def ASSERT_FLOAT_EQ
236 /// See `EXPECT_FLOAT_EQ`.
237 #define ASSERT_FLOAT_EQ(lhs, rhs) \
238   _PW_TEST_ASSERT(                \
239       _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<float>::epsilon()))
240 
241 /// @def ASSERT_DOUBLE_EQ
242 /// See `EXPECT_DOUBLE_EQ`.
243 #define ASSERT_DOUBLE_EQ(lhs, rhs) \
244   _PW_TEST_ASSERT(                 \
245       _PW_TEST_NEAR(lhs, rhs, 4 * std::numeric_limits<double>::epsilon()))
246 
247 /// @def ASSERT_STREQ
248 /// See `EXPECT_STREQ`.
249 #define ASSERT_STREQ(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, ==))
250 
251 /// @def ASSERT_STRNE
252 /// See `EXPECT_STRNE`.
253 #define ASSERT_STRNE(lhs, rhs) _PW_TEST_ASSERT(_PW_TEST_C_STR(lhs, rhs, !=))
254 
255 /// @def ADD_FAILURE
256 /// Generates a non-fatal failure with a generic message.
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 
262 /// @def GTEST_FAIL
263 ///
264 /// Alias of `FAIL`.
265 #define GTEST_FAIL() return ADD_FAILURE()
266 
267 /// @def GTEST_SKIP
268 /// Skips test at runtime. Skips are neither successful nor failed. They
269 /// abort the current function.
270 #define GTEST_SKIP()                                                     \
271   ::pw::unit_test::internal::Framework::Get().CurrentTestSkip(__LINE__); \
272   return _PW_UNIT_TEST_LOG
273 
274 /// @def FAIL
275 /// Generates a fatal failure with a generic message.
276 ///
277 /// If this generic name is clashing with other code, set
278 /// `GTEST_DONT_DEFINE_FAIL` to 1 and use `GTEST_FAIL` instead.
279 #if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
280 #define FAIL() GTEST_FAIL()
281 #endif  // !GTEST_DONT_DEFINE_FAIL
282 
283 /// @def GTEST_SUCCEED
284 ///
285 /// Alias of `SUCCEED`.
286 #define GTEST_SUCCEED()                                                \
287   ::pw::unit_test::internal::Framework::Get().CurrentTestExpectSimple( \
288       "(success)", "(success)", __LINE__, true);                       \
289   _PW_UNIT_TEST_LOG
290 
291 /// @def SUCCEED
292 ///
293 /// Generates success with a generic message.
294 ///
295 /// If this generic name is conflicting with other code, set
296 /// `GTEST_DONT_DEFINE_SUCCEED` to 1 and use `GTEST_SUCCEED` instead.
297 #if !(defined(GTEST_DONT_DEFINE_SUCCEED) && GTEST_DONT_DEFINE_SUCCEED)
298 #define SUCCEED() GTEST_SUCCEED()
299 #endif  // !GTEST_DONT_DEFINE_SUCCEED
300 
301 /// @def RUN_ALL_TESTS
302 /// The `pw_unit_test` framework entrypoint. Runs every registered test case
303 /// and dispatches the results through the event handler.
304 ///
305 /// @pre An event handler has been registered before calling `RUN_ALL_TESTS`.
306 ///
307 /// @returns A status of 0 if all tests passed, or non-zero if there were any
308 /// failures. This is compatible with GoogleTest.
309 #define RUN_ALL_TESTS() \
310   ::pw::unit_test::internal::Framework::Get().RunAllTests()
311 
312 /// @def GTEST_HAS_DEATH_TEST
313 /// Death tests are not supported. The `*_DEATH_IF_SUPPORTED` macros do nothing.
314 #define GTEST_HAS_DEATH_TEST 0
315 
316 /// @def EXPECT_DEATH_IF_SUPPORTED
317 /// See `GTEST_HAS_DEATH_TEST`.
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 
325 /// @def ASSERT_DEATH_IF_SUPPORTED
326 /// See `GTEST_HAS_DEATH_TEST`.
327 #define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
328   EXPECT_DEATH_IF_SUPPORTED(statement, regex)
329 
330 namespace pw {
331 
332 #if PW_CXX_STANDARD_IS_SUPPORTED(17)
333 
334 namespace 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.
353 template <typename T>
UnknownTypeToString(const T & value,span<char> buffer)354 StatusWithSize 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 
396 namespace unit_test {
397 namespace internal {
398 
399 class Test;
400 class TestInfo;
401 
402 // Types of SetUpTestSuite() and TearDownTestSuite() functions.
403 using SetUpTestSuiteFunc = void (*)();
404 using TearDownTestSuiteFunc = void (*)();
405 
406 // Used to tag arguments to EXPECT_STREQ/EXPECT_STRNE so they are treated like C
407 // strings rather than pointers.
408 struct CStringArg {
409   const char* const c_str;
410 };
411 
MaxPaddingNeededToRaiseAlignment(size_t current_align,size_t new_align)412 constexpr 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.
423 class Framework {
424  public:
Framework()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 
Get()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.
RegisterEventHandler(EventHandler * 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.
SetTestSuitesToRun(span<std::string_view> test_suites)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.
IsSkipped()465   bool IsSkipped() const { return current_result_ == TestResult::kSkipped; }
466 
467   // Whether the current test has failed.
HasFailure()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>
CreateAndRunTest(const TestInfo & test_info)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>
CurrentTestExpect(Expectation expectation,const Lhs & lhs,const Rhs & rhs,const Epsilon & epsilon,const char * expression,int line)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>
CurrentTestExpect(Expectation expectation,const Lhs & lhs,const Rhs & rhs,const char * expectation_string,const char * expression,int line)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.
ConvertForPrint(const char * str)590   static constexpr const void* ConvertForPrint(const char* str) { return str; }
591 
ConvertForPrint(char * str)592   static constexpr const void* ConvertForPrint(char* str) { return str; }
593 
ConvertForPrint(CStringArg value)594   static constexpr const char* ConvertForPrint(CStringArg value) {
595     return value.c_str;
596   }
597 
598   template <typename T>
ConvertForPrint(T && value)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.
649 class TestInfo {
650  public:
TestInfo(const char * const test_suite_name,const char * const test_name,const char * const file_name,void (* run_func)(const TestInfo &))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.
test_case()665   const TestCase& test_case() const { return test_case_; }
666 
667   bool enabled() const;
668 
run()669   void run() const { run_(*this); }
670 
next()671   TestInfo* next() const { return next_; }
set_next(TestInfo * 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.
699 class Test {
700  public:
701   Test(const Test&) = delete;
702   Test& operator=(const Test&) = delete;
703 
704   virtual ~Test() = default;
705 
SetUpTestSuite()706   static void SetUpTestSuite() {}
TearDownTestSuite()707   static void TearDownTestSuite() {}
708 
HasFailure()709   static bool HasFailure() { return Framework::Get().HasFailure(); }
710 
711   // Runs the unit test.
PigweedTestRun()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.
SetUp()729   virtual void SetUp() {}
730 
731   // Called immediately after executing the test body.
TearDown()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.
HasNoUnderscores(const char * suite)742 constexpr 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.
761 class IgnoreLogs {
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.
773 class ReturnHelper {
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)
SetTestSuitesToRun(span<std::string_view> test_suites)790 inline 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 
912 namespace testing {
913 
914 // Alias Test as ::testing::Test for GoogleTest compatibility.
915 using Test = ::pw::unit_test::internal::Test;
916 
917 // Provide a no-op init routine for GoogleTest compatibility.
InitGoogleTest(int *,char **)918 inline void InitGoogleTest(int*, char**) {}
919 
920 }  // namespace testing
921