//===-- Base class for libc unittests ---------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_TEST_UNITTEST_LIBCTEST_H #define LLVM_LIBC_TEST_UNITTEST_LIBCTEST_H // This is defined as a simple macro in test.h so that it exists for platforms // that don't use our test infrastructure. It's defined as a proper function // below. #include "src/__support/macros/config.h" #ifdef libc_make_test_file_path #undef libc_make_test_file_path #endif // libc_make_test_file_path // This is defined as a macro here to avoid namespace issues. #define libc_make_test_file_path(file_name) … // This file can only include headers from src/__support/ or test/UnitTest. No // other headers should be included. #include "PlatformDefs.h" #include "src/__support/CPP/string.h" #include "src/__support/CPP/string_view.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/c_string.h" #include "test/UnitTest/ExecuteFunction.h" #include "test/UnitTest/TestLogger.h" namespace LIBC_NAMESPACE_DECL { namespace testing { // Only the following conditions are supported. Notice that we do not have // a TRUE or FALSE condition. That is because, C library functions do not // return boolean values, but use integral return values to indicate true or // false conditions. Hence, it is more appropriate to use the other comparison // conditions for such cases. enum class TestCond { … }; struct MatcherBase { … }; template <typename T> struct Matcher : public MatcherBase { … }; namespace internal { // A simple location object to allow consistent passing of __FILE__ and // __LINE__. struct Location { … }; // Supports writing a failing Location to tlog. TestLogger &operator<<(TestLogger &logger, Location Loc); #define LIBC_TEST_LOC_() … // Object to forward custom logging after the EXPECT / ASSERT macros. struct Message { … }; // A trivial object to catch the Message, this enables custom logging and // returning from the test function, see LIBC_TEST_SCAFFOLDING_ below. struct Failure { … }; struct RunContext { … }; template <typename ValType> bool test(RunContext *Ctx, TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, const char *RHSStr, Location Loc); } // namespace internal struct TestOptions { … }; // NOTE: One should not create instances and call methods on them directly. One // should use the macros TEST or TEST_F to write test cases. class Test { … }; extern int argc; extern char **argv; extern char **envp; namespace internal { constexpr bool same_prefix(char const *lhs, char const *rhs, int const len) { … } constexpr bool valid_prefix(char const *lhs) { … } // 'str' is a null terminated string of the form // "const char *LIBC_NAMESPACE::testing::internal::GetTypeName() [ParamType = // XXX]" We return the substring that start at character '[' or a default // message. constexpr char const *GetPrettyFunctionParamType(char const *str) { … } // This function recovers ParamType at compile time by using __PRETTY_FUNCTION__ // It can be customized by using the REGISTER_TYPE_NAME macro below. template <typename ParamType> static constexpr const char *GetTypeName() { … } template <typename T> static inline void GenerateName(char *buffer, int buffer_size, const char *prefix) { … } // TestCreator implements a linear hierarchy of test instances, effectively // instanciating all tests with Types in a single object. template <template <typename> class TemplatedTestClass, typename... Types> struct TestCreator; TestCreator<TemplatedTestClass, Head, Tail...>; TestCreator<TemplatedTestClass>; // A type list to declare the set of types to instantiate the tests with. template <typename... Types> struct TypeList { … }; } // namespace internal // Make TypeList visible in LIBC_NAMESPACE::testing. TypeList; CString libc_make_test_file_path_func(const char *file_name); } // namespace testing } // namespace LIBC_NAMESPACE_DECL // For TYPED_TEST and TYPED_TEST_F below we need to display which type was used // to run the test. The default will return the fully qualified canonical type // but it can be difficult to read. We provide the following macro to allow the // client to register the type name as they see it in the code. #define REGISTER_TYPE_NAME(TYPE) … #define TYPED_TEST(SuiteName, TestName, TypeList) … #define TYPED_TEST_F(SuiteClass, TestName, TypeList) … #define TEST(SuiteName, TestName) … #define TEST_F(SuiteClass, TestName) … // If RET_OR_EMPTY is the 'return' keyword we perform an early return which // corresponds to an assert. If it is empty the execution continues, this // corresponds to an expect. // // The 'else' clause must not be enclosed into braces so that the << operator // can be used to fill the Message. // // TEST is usually implemented as a function performing checking logic and // returning a boolean. This expression is responsible for logging the // diagnostic in case of failure. #define LIBC_TEST_SCAFFOLDING_(TEST, RET_OR_EMPTY) … #define LIBC_TEST_BINOP_(COND, LHS, RHS, RET_OR_EMPTY) … //////////////////////////////////////////////////////////////////////////////// // Binary operations corresponding to the TestCond enum. #define EXPECT_EQ(LHS, RHS) … #define ASSERT_EQ(LHS, RHS) … #define EXPECT_NE(LHS, RHS) … #define ASSERT_NE(LHS, RHS) … #define EXPECT_LT(LHS, RHS) … #define ASSERT_LT(LHS, RHS) … #define EXPECT_LE(LHS, RHS) … #define ASSERT_LE(LHS, RHS) … #define EXPECT_GT(LHS, RHS) … #define ASSERT_GT(LHS, RHS) … #define EXPECT_GE(LHS, RHS) … #define ASSERT_GE(LHS, RHS) … //////////////////////////////////////////////////////////////////////////////// // Boolean checks are handled as comparison to the true / false values. #define EXPECT_TRUE(VAL) … #define ASSERT_TRUE(VAL) … #define EXPECT_FALSE(VAL) … #define ASSERT_FALSE(VAL) … //////////////////////////////////////////////////////////////////////////////// // String checks. #define LIBC_TEST_STR_(TEST_FUNC, LHS, RHS, RET_OR_EMPTY) … #define EXPECT_STREQ(LHS, RHS) … #define ASSERT_STREQ(LHS, RHS) … #define EXPECT_STRNE(LHS, RHS) … #define ASSERT_STRNE(LHS, RHS) … //////////////////////////////////////////////////////////////////////////////// // Subprocess checks. #ifdef ENABLE_SUBPROCESS_TESTS #define LIBC_TEST_PROCESS_(TEST_FUNC, FUNC, VALUE, RET_OR_EMPTY) … #define EXPECT_EXITS(FUNC, EXIT) … #define ASSERT_EXITS(FUNC, EXIT) … #define EXPECT_DEATH(FUNC, SIG) … #define ASSERT_DEATH(FUNC, SIG) … #endif // ENABLE_SUBPROCESS_TESTS //////////////////////////////////////////////////////////////////////////////// // Custom matcher checks. #define LIBC_TEST_MATCH_(MATCHER, MATCH, MATCHER_STR, MATCH_STR, RET_OR_EMPTY) … #define EXPECT_THAT(MATCH, MATCHER) … #define ASSERT_THAT(MATCH, MATCHER) … #define WITH_SIGNAL(X) … #define LIBC_TEST_HAS_MATCHERS() … #endif // LLVM_LIBC_TEST_UNITTEST_LIBCTEST_H