diff --git a/libc/utils/UnitTest/CMakeLists.txt b/libc/utils/UnitTest/CMakeLists.txt --- a/libc/utils/UnitTest/CMakeLists.txt +++ b/libc/utils/UnitTest/CMakeLists.txt @@ -1,7 +1,8 @@ add_llvm_library( LibcUnitTest - Test.cpp Test.h + LibcTest.cpp + LibcTest.h ) target_include_directories(LibcUnitTest PUBLIC ${LIBC_SOURCE_DIR}) add_dependencies(LibcUnitTest libc.utils.CPP.standalone_cpp) diff --git a/libc/utils/UnitTest/FuchsiaTest.h b/libc/utils/UnitTest/FuchsiaTest.h new file mode 100644 --- /dev/null +++ b/libc/utils/UnitTest/FuchsiaTest.h @@ -0,0 +1,20 @@ +//===-- Header for setting up the Fuchsia tests -----------------*- 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_UTILS_UNITTEST_FUCHSIATEST_H +#define LLVM_LIBC_UTILS_UNITTEST_FUCHSIATEST_H + +#include +// isascii is being undef'd because Fuchsia's headers define a macro for +// isascii. that macro causes errors when isascii_test.cpp references +// __llvm_libc::isascii since the macro is applied first. +#ifdef isascii +#undef isascii +#endif + +#endif // LLVM_LIBC_UTILS_UNITTEST_FUCHSIATEST_H diff --git a/libc/utils/UnitTest/Test.h b/libc/utils/UnitTest/LibcTest.h copy from libc/utils/UnitTest/Test.h copy to libc/utils/UnitTest/LibcTest.h --- a/libc/utils/UnitTest/Test.h +++ b/libc/utils/UnitTest/LibcTest.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_UTILS_UNITTEST_H -#define LLVM_LIBC_UTILS_UNITTEST_H +#ifndef LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H +#define LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H // This file can only include headers from utils/CPP/ or utils/testutils. No // other headers should be included. @@ -257,4 +257,4 @@ return; \ } while (0) -#endif // LLVM_LIBC_UTILS_UNITTEST_H +#endif // LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H diff --git a/libc/utils/UnitTest/Test.cpp b/libc/utils/UnitTest/LibcTest.cpp rename from libc/utils/UnitTest/Test.cpp rename to libc/utils/UnitTest/LibcTest.cpp --- a/libc/utils/UnitTest/Test.cpp +++ b/libc/utils/UnitTest/LibcTest.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "Test.h" +#include "LibcTest.h" #include "utils/testutils/ExecuteFunction.h" #include diff --git a/libc/utils/UnitTest/Test.h b/libc/utils/UnitTest/Test.h --- a/libc/utils/UnitTest/Test.h +++ b/libc/utils/UnitTest/Test.h @@ -1,4 +1,4 @@ -//===-- Base class for libc unittests ---------------------------*- C++ -*-===// +//===-- Header selector 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. @@ -6,255 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_UTILS_UNITTEST_H -#define LLVM_LIBC_UTILS_UNITTEST_H +#ifndef LLVM_LIBC_UTILS_UNITTEST_TEST_H +#define LLVM_LIBC_UTILS_UNITTEST_TEST_H -// This file can only include headers from utils/CPP/ or utils/testutils. No -// other headers should be included. +#ifdef LLVM_LIBC_TEST_USE_FUCHSIA +#include "FuchsiaTest.h" +#else +#include "LibcTest.h" +#endif -#include "utils/CPP/TypeTraits.h" -#include "utils/testutils/ExecuteFunction.h" -#include "utils/testutils/StreamWrapper.h" - -namespace __llvm_libc { -namespace testing { - -class RunContext; - -// Only the following conditions are supported. Notice that we do not have -// a TRUE or FALSE condition. That is because, C library funtions 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 TestCondition { - Cond_None, - Cond_EQ, - Cond_NE, - Cond_LT, - Cond_LE, - Cond_GT, - Cond_GE, -}; - -namespace internal { - -template -bool test(RunContext *Ctx, TestCondition Cond, ValType LHS, ValType RHS, - const char *LHSStr, const char *RHSStr, const char *File, - unsigned long Line); - -} // namespace internal - -struct MatcherBase { - virtual ~MatcherBase() {} - virtual void explainError(testutils::StreamWrapper &OS) { - OS << "unknown error\n"; - } -}; - -template struct Matcher : public MatcherBase { bool match(T &t); }; - -// 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 { -private: - Test *Next = nullptr; - RunContext *Ctx = nullptr; - - void setContext(RunContext *C) { Ctx = C; } - -public: - virtual ~Test() {} - virtual void SetUp() {} - virtual void TearDown() {} - - static int runTests(); - -protected: - static void addTest(Test *T); - - // We make use of a template function, with |LHS| and |RHS| as explicit - // parameters, for enhanced type checking. Other gtest like unittest - // frameworks have a similar function which takes a boolean argument - // instead of the explicit |LHS| and |RHS| arguments. This boolean argument - // is the result of the |Cond| operation on |LHS| and |RHS|. Though not bad, - // |Cond| on mismatched |LHS| and |RHS| types can potentially succeed because - // of type promotion. - template ::Value, int> = 0> - bool test(TestCondition Cond, ValType LHS, ValType RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { - return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, File, Line); - } - - template < - typename ValType, - cpp::EnableIfType::Value, ValType> = nullptr> - bool test(TestCondition Cond, ValType LHS, ValType RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { - return internal::test(Ctx, Cond, (unsigned long long)LHS, - (unsigned long long)RHS, LHSStr, RHSStr, File, Line); - } - - bool testStrEq(const char *LHS, const char *RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line); - - bool testStrNe(const char *LHS, const char *RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line); - - bool testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line); - - bool testProcessExits(testutils::FunctionCaller *Func, int ExitCode, - const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); - - bool testProcessKilled(testutils::FunctionCaller *Func, int Signal, - const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); - - template testutils::FunctionCaller *createCallable(Func f) { - struct Callable : public testutils::FunctionCaller { - Func f; - Callable(Func f) : f(f) {} - void operator()() override { f(); } - }; - - return new Callable(f); - } - -private: - virtual void Run() = 0; - virtual const char *getName() const = 0; - - static Test *Start; - static Test *End; -}; - -} // namespace testing -} // namespace __llvm_libc - -#define TEST(SuiteName, TestName) \ - class SuiteName##_##TestName : public __llvm_libc::testing::Test { \ - public: \ - SuiteName##_##TestName() { addTest(this); } \ - void Run() override; \ - const char *getName() const override { return #SuiteName "." #TestName; } \ - }; \ - SuiteName##_##TestName SuiteName##_##TestName##_Instance; \ - void SuiteName##_##TestName::Run() - -#define TEST_F(SuiteClass, TestName) \ - class SuiteClass##_##TestName : public SuiteClass { \ - public: \ - SuiteClass##_##TestName() { addTest(this); } \ - void Run() override; \ - const char *getName() const override { return #SuiteClass "." #TestName; } \ - }; \ - SuiteClass##_##TestName SuiteClass##_##TestName##_Instance; \ - void SuiteClass##_##TestName::Run() - -#define EXPECT_EQ(LHS, RHS) \ - this->test(__llvm_libc::testing::Cond_EQ, (LHS), (RHS), #LHS, #RHS, \ - __FILE__, __LINE__) -#define ASSERT_EQ(LHS, RHS) \ - if (!EXPECT_EQ(LHS, RHS)) \ - return - -#define EXPECT_NE(LHS, RHS) \ - this->test(__llvm_libc::testing::Cond_NE, (LHS), (RHS), #LHS, #RHS, \ - __FILE__, __LINE__) -#define ASSERT_NE(LHS, RHS) \ - if (!EXPECT_NE(LHS, RHS)) \ - return - -#define EXPECT_LT(LHS, RHS) \ - this->test(__llvm_libc::testing::Cond_LT, (LHS), (RHS), #LHS, #RHS, \ - __FILE__, __LINE__) -#define ASSERT_LT(LHS, RHS) \ - if (!EXPECT_LT(LHS, RHS)) \ - return - -#define EXPECT_LE(LHS, RHS) \ - this->test(__llvm_libc::testing::Cond_LE, (LHS), (RHS), #LHS, #RHS, \ - __FILE__, __LINE__) -#define ASSERT_LE(LHS, RHS) \ - if (!EXPECT_LE(LHS, RHS)) \ - return - -#define EXPECT_GT(LHS, RHS) \ - this->test(__llvm_libc::testing::Cond_GT, (LHS), (RHS), #LHS, #RHS, \ - __FILE__, __LINE__) -#define ASSERT_GT(LHS, RHS) \ - if (!EXPECT_GT(LHS, RHS)) \ - return - -#define EXPECT_GE(LHS, RHS) \ - this->test(__llvm_libc::testing::Cond_GE, (LHS), (RHS), #LHS, #RHS, \ - __FILE__, __LINE__) -#define ASSERT_GE(LHS, RHS) \ - if (!EXPECT_GE(LHS, RHS)) \ - return - -#define EXPECT_STREQ(LHS, RHS) \ - this->testStrEq((LHS), (RHS), #LHS, #RHS, __FILE__, __LINE__) -#define ASSERT_STREQ(LHS, RHS) \ - if (!EXPECT_STREQ(LHS, RHS)) \ - return - -#define EXPECT_STRNE(LHS, RHS) \ - this->testStrNe((LHS), (RHS), #LHS, #RHS, __FILE__, __LINE__) -#define ASSERT_STRNE(LHS, RHS) \ - if (!EXPECT_STRNE(LHS, RHS)) \ - return - -#define EXPECT_TRUE(VAL) EXPECT_EQ((VAL), true) - -#define ASSERT_TRUE(VAL) \ - if (!EXPECT_TRUE(VAL)) \ - return - -#define EXPECT_FALSE(VAL) EXPECT_EQ((VAL), false) - -#define ASSERT_FALSE(VAL) \ - if (!EXPECT_FALSE(VAL)) \ - return - -#define EXPECT_EXITS(FUNC, EXIT) \ - this->testProcessExits(__llvm_libc::testing::Test::createCallable(FUNC), \ - EXIT, #FUNC, #EXIT, __FILE__, __LINE__) - -#define ASSERT_EXITS(FUNC, EXIT) \ - if (!EXPECT_EXITS(FUNC, EXIT)) \ - return - -#define EXPECT_DEATH(FUNC, SIG) \ - this->testProcessKilled(__llvm_libc::testing::Test::createCallable(FUNC), \ - SIG, #FUNC, #SIG, __FILE__, __LINE__) - -#define ASSERT_DEATH(FUNC, EXIT) \ - if (!EXPECT_DEATH(FUNC, EXIT)) \ - return - -#define __CAT1(a, b) a##b -#define __CAT(a, b) __CAT1(a, b) -#define UNIQUE_VAR(prefix) __CAT(prefix, __LINE__) - -#define EXPECT_THAT(MATCH, MATCHER) \ - do { \ - auto UNIQUE_VAR(__matcher) = (MATCHER); \ - this->testMatch(UNIQUE_VAR(__matcher).match((MATCH)), \ - UNIQUE_VAR(__matcher), #MATCH, #MATCHER, __FILE__, \ - __LINE__); \ - } while (0) - -#define ASSERT_THAT(MATCH, MATCHER) \ - do { \ - auto UNIQUE_VAR(__matcher) = (MATCHER); \ - if (!this->testMatch(UNIQUE_VAR(__matcher).match((MATCH)), \ - UNIQUE_VAR(__matcher), #MATCH, #MATCHER, __FILE__, \ - __LINE__)) \ - return; \ - } while (0) - -#endif // LLVM_LIBC_UTILS_UNITTEST_H +#endif // LLVM_LIBC_UTILS_UNITTEST_TEST_H