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)
--- /dev/null
+//===-- 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 <zxtest/zxtest.h>
+// 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
//
//===----------------------------------------------------------------------===//
-#include "Test.h"
+#include "LibcTest.h"
#include "utils/testutils/ExecuteFunction.h"
#include <cassert>
--- /dev/null
+//===-- 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_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.
+
+#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 <typename ValType>
+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 <typename T> 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 <typename ValType,
+ cpp::EnableIfType<cpp::IsIntegral<ValType>::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<cpp::IsPointerType<ValType>::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 <typename Func> 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_LIBCTEST_H
-//===-- 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.
//
//===----------------------------------------------------------------------===//
-#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 <typename ValType>
-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 <typename T> 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 <typename ValType,
- cpp::EnableIfType<cpp::IsIntegral<ValType>::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<cpp::IsPointerType<ValType>::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 <typename Func> 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