1 //===------------------ Base class for libc unittests -----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // This file can only include headers from utils/CPP/. No other header should be 10 // included. 11 12 #include "utils/CPP/TypeTraits.h" 13 14 namespace __llvm_libc { 15 namespace testing { 16 17 class RunContext; 18 19 // Only the following conditions are supported. Notice that we do not have 20 // a TRUE or FALSE condition. That is because, C library funtions do not 21 // return boolean values, but use integral return values to indicate true or 22 // false conditions. Hence, it is more appropriate to use the other comparison 23 // condtions for such cases. 24 enum TestCondition { 25 Cond_None, 26 Cond_EQ, 27 Cond_NE, 28 Cond_LT, 29 Cond_LE, 30 Cond_GT, 31 Cond_GE, 32 }; 33 34 namespace internal { 35 36 template <typename ValType> 37 bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, ValType RHS, 38 const char *LHSStr, const char *RHSStr, const char *File, 39 unsigned long Line); 40 41 } // namespace internal 42 43 // NOTE: One should not create instances and call methods on them directly. One 44 // should use the macros TEST or TEST_F to write test cases. 45 class Test { 46 private: 47 Test *Next = nullptr; 48 49 public: 50 virtual ~Test() {} 51 virtual void SetUp() {} 52 virtual void TearDown() {} 53 54 static int runTests(); 55 56 protected: 57 static void addTest(Test *T); 58 59 // We make use of a template function, with |LHS| and |RHS| as explicit 60 // parameters, for enhanced type checking. Other gtest like unittest 61 // frameworks have a similar function which takes a boolean argument 62 // instead of the explicit |LHS| and |RHS| arguments. This boolean argument 63 // is the result of the |Cond| operation on |LHS| and |RHS|. Though not bad, 64 // |Cond| on mismatched |LHS| and |RHS| types can potentially succeed because 65 // of type promotion. 66 template <typename ValType, 67 cpp::EnableIfType<cpp::IsIntegral<ValType>::Value, ValType> = 0> 68 static bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, 69 ValType RHS, const char *LHSStr, const char *RHSStr, 70 const char *File, unsigned long Line) { 71 return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, File, Line); 72 } 73 74 template < 75 typename ValType, 76 cpp::EnableIfType<cpp::IsPointerType<ValType>::Value, ValType> = nullptr> 77 static bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, 78 ValType RHS, const char *LHSStr, const char *RHSStr, 79 const char *File, unsigned long Line) { 80 return internal::test(Ctx, Cond, (unsigned long long)LHS, 81 (unsigned long long)RHS, LHSStr, RHSStr, File, Line); 82 } 83 84 static bool testStrEq(RunContext &Ctx, const char *LHS, const char *RHS, 85 const char *LHSStr, const char *RHSStr, 86 const char *File, unsigned long Line); 87 88 static bool testStrNe(RunContext &Ctx, const char *LHS, const char *RHS, 89 const char *LHSStr, const char *RHSStr, 90 const char *File, unsigned long Line); 91 92 private: 93 virtual void Run(RunContext &Ctx) = 0; 94 virtual const char *getName() const = 0; 95 96 static Test *Start; 97 static Test *End; 98 }; 99 100 } // namespace testing 101 } // namespace __llvm_libc 102 103 #define TEST(SuiteName, TestName) \ 104 class SuiteName##_##TestName : public __llvm_libc::testing::Test { \ 105 public: \ 106 SuiteName##_##TestName() { addTest(this); } \ 107 void Run(__llvm_libc::testing::RunContext &) override; \ 108 const char *getName() const override { return #SuiteName "." #TestName; } \ 109 }; \ 110 SuiteName##_##TestName SuiteName##_##TestName##_Instance; \ 111 void SuiteName##_##TestName::Run(__llvm_libc::testing::RunContext &Ctx) 112 113 #define TEST_F(SuiteClass, TestName) \ 114 class SuiteClass##_##TestName : public SuiteClass { \ 115 public: \ 116 SuiteClass##_##TestName() { addTest(this); } \ 117 void Run(__llvm_libc::testing::RunContext &) override; \ 118 const char *getName() const override { return #SuiteClass "." #TestName; } \ 119 }; \ 120 SuiteClass##_##TestName SuiteClass##_##TestName##_Instance; \ 121 void SuiteClass##_##TestName::Run(__llvm_libc::testing::RunContext &Ctx) 122 123 #define EXPECT_EQ(LHS, RHS) \ 124 __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_EQ, (LHS), \ 125 (RHS), #LHS, #RHS, __FILE__, __LINE__) 126 #define ASSERT_EQ(LHS, RHS) \ 127 if (!EXPECT_EQ(LHS, RHS)) \ 128 return 129 130 #define EXPECT_NE(LHS, RHS) \ 131 __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_NE, (LHS), \ 132 (RHS), #LHS, #RHS, __FILE__, __LINE__) 133 #define ASSERT_NE(LHS, RHS) \ 134 if (!EXPECT_NE(LHS, RHS)) \ 135 return 136 137 #define EXPECT_LT(LHS, RHS) \ 138 __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_LT, (LHS), \ 139 (RHS), #LHS, #RHS, __FILE__, __LINE__) 140 #define ASSERT_LT(LHS, RHS) \ 141 if (!EXPECT_LT(LHS, RHS)) \ 142 return 143 144 #define EXPECT_LE(LHS, RHS) \ 145 __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_LE, (LHS), \ 146 (RHS), #LHS, #RHS, __FILE__, __LINE__) 147 #define ASSERT_LE(LHS, RHS) \ 148 if (!EXPECT_LE(LHS, RHS)) \ 149 return 150 151 #define EXPECT_GT(LHS, RHS) \ 152 __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_GT, (LHS), \ 153 (RHS), #LHS, #RHS, __FILE__, __LINE__) 154 #define ASSERT_GT(LHS, RHS) \ 155 if (!EXPECT_GT(LHS, RHS)) \ 156 return 157 158 #define EXPECT_GE(LHS, RHS) \ 159 __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_GE, (LHS), \ 160 (RHS), #LHS, #RHS, __FILE__, __LINE__) 161 #define ASSERT_GE(LHS, RHS) \ 162 if (!EXPECT_GE(LHS, RHS)) \ 163 return 164 165 #define EXPECT_STREQ(LHS, RHS) \ 166 __llvm_libc::testing::Test::testStrEq(Ctx, (LHS), (RHS), #LHS, #RHS, \ 167 __FILE__, __LINE__) 168 #define ASSERT_STREQ(LHS, RHS) \ 169 if (!EXPECT_STREQ(LHS, RHS)) \ 170 return 171 172 #define EXPECT_STRNE(LHS, RHS) \ 173 __llvm_libc::testing::Test::testStrNe(Ctx, (LHS), (RHS), #LHS, #RHS, \ 174 __FILE__, __LINE__) 175 #define ASSERT_STRNE(LHS, RHS) \ 176 if (!EXPECT_STRNE(LHS, RHS)) \ 177 return 178 179 #define EXPECT_TRUE(VAL) EXPECT_EQ((VAL), true) 180 181 #define ASSERT_TRUE(VAL) \ 182 if (!EXPECT_TRUE(VAL)) \ 183 return 184 185 #define EXPECT_FALSE(VAL) EXPECT_EQ((VAL), false) 186 187 #define ASSERT_FALSE(VAL) \ 188 if (!EXPECT_FALSE(VAL)) \ 189 return 190