1 //===------------------ Base class for libc unittests -----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file should stricly not include any other file. Not even standard
15 // We define our own EnableIf and IsIntegerType traits because we do not want to
16 // include even the standard header <type_traits>.
17 template <bool B, typename T> struct EnableIf;
18 template <typename T> struct EnableIf<true, T> { typedef T Type; };
20 template <bool B, typename T>
21 using EnableIfType = typename EnableIf<B, T>::Type;
23 template <typename Type> struct IsIntegerType {
24 static const bool Value = false;
27 template <> struct IsIntegerType<char> { static const bool Value = true; };
28 template <> struct IsIntegerType<unsigned char> {
29 static const bool Value = true;
32 template <> struct IsIntegerType<short> { static const bool Value = true; };
33 template <> struct IsIntegerType<unsigned short> {
34 static const bool Value = true;
37 template <> struct IsIntegerType<int> { static const bool Value = true; };
38 template <> struct IsIntegerType<unsigned int> {
39 static const bool Value = true;
42 template <> struct IsIntegerType<long> { static const bool Value = true; };
43 template <> struct IsIntegerType<unsigned long> {
44 static const bool Value = true;
47 template <> struct IsIntegerType<long long> { static const bool Value = true; };
48 template <> struct IsIntegerType<unsigned long long> {
49 static const bool Value = true;
52 template <typename T> struct IsPointerType;
54 template <typename T> struct IsPointerType<T *> {
55 static const bool Value = true;
60 // Only the following conditions are supported. Notice that we do not have
61 // a TRUE or FALSE condition. That is because, C library funtions do not
62 // return, but use integral return values to indicate true or false
63 // conditions. Hence, it is more appropriate to use the other comparison
64 // condtions for such cases.
77 template <typename ValType>
78 bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, ValType RHS,
79 const char *LHSStr, const char *RHSStr, const char *File,
82 } // namespace internal
84 // NOTE: One should not create instances and call methods on them directly. One
85 // should use the macros TEST or TEST_F to write test cases.
92 virtual void SetUp() {}
93 virtual void TearDown() {}
95 static int runTests();
98 static void addTest(Test *T);
100 // We make use of a template function, with |LHS| and |RHS| as explicit
101 // parameters, for enhanced type checking. Other gtest like test unittest
102 // frameworks have a similar functions which takes a boolean argument
103 // instead of the explicit |LHS| and |RHS| arguments. This boolean argument
104 // is the result of the |Cond| operation on |LHS| and |RHS|. Though not bad,
105 // mismatched |LHS| and |RHS| types can potentially succeed because of type
107 template <typename ValType,
108 EnableIfType<IsIntegerType<ValType>::Value, ValType> = 0>
109 static bool test(RunContext &Ctx, TestCondition Cond, ValType LHS,
110 ValType RHS, const char *LHSStr, const char *RHSStr,
111 const char *File, unsigned long Line) {
112 return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, File, Line);
115 template <typename ValType,
116 EnableIfType<IsPointerType<ValType>::Value, ValType> = nullptr>
117 static bool test(RunContext &Ctx, TestCondition Cond, ValType LHS,
118 ValType RHS, const char *LHSStr, const char *RHSStr,
119 const char *File, unsigned long Line) {
120 return internal::test(Ctx, Cond, (unsigned long long)LHS,
121 (unsigned long long)RHS, LHSStr, RHSStr, File, Line);
124 static bool testStrEq(RunContext &Ctx, const char *LHS, const char *RHS,
125 const char *LHSStr, const char *RHSStr,
126 const char *File, unsigned long Line);
128 static bool testStrNe(RunContext &Ctx, const char *LHS, const char *RHS,
129 const char *LHSStr, const char *RHSStr,
130 const char *File, unsigned long Line);
133 virtual void Run(RunContext &Ctx) = 0;
134 virtual const char *getName() const = 0;
140 } // namespace testing
141 } // namespace llvm_libc
143 #define TEST(SuiteName, TestName) \
144 class SuiteName##_##TestName : public llvm_libc::testing::Test { \
146 SuiteName##_##TestName() { addTest(this); } \
147 void Run(llvm_libc::testing::RunContext &) override; \
148 const char *getName() const override { return #SuiteName "." #TestName; } \
150 SuiteName##_##TestName SuiteName##_##TestName##_Instance; \
151 void SuiteName##_##TestName::Run(llvm_libc::testing::RunContext &Ctx)
153 #define TEST_F(SuiteClass, TestName) \
154 class SuiteClass##_##TestName : public SuiteClass { \
156 SuiteClass##_##TestName() { addTest(this); } \
157 void Run(llvm_libc::testing::RunContext &) override; \
158 const char *getName() const override { return #SuiteClass "." #TestName; } \
160 SuiteClass##_##TestName SuiteClass##_##TestName##_Instance; \
161 void SuiteClass##_##TestName::Run(llvm_libc::testing::RunContext &Ctx)
163 #define EXPECT_EQ(LHS, RHS) \
164 llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_EQ, (LHS), \
165 (RHS), #LHS, #RHS, __FILE__, __LINE__)
166 #define ASSERT_EQ(LHS, RHS) \
167 if (!EXPECT_EQ(LHS, RHS)) \
170 #define EXPECT_NE(LHS, RHS) \
171 llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_NE, (LHS), \
172 (RHS), #LHS, #RHS, __FILE__, __LINE__)
173 #define ASSERT_NE(LHS, RHS) \
174 if (!EXPECT_NE(LHS, RHS)) \
177 #define EXPECT_LT(LHS, RHS) \
178 llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_LT, (LHS), \
179 (RHS), #LHS, #RHS, __FILE__, __LINE__)
180 #define ASSERT_LT(LHS, RHS) \
181 if (!EXPECT_LT(LHS, RHS)) \
184 #define EXPECT_LE(LHS, RHS) \
185 llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_LE, (LHS), \
186 (RHS), #LHS, #RHS, __FILE__, __LINE__)
187 #define ASSERT_LE(LHS, RHS) \
188 if (!EXPECT_LE(LHS, RHS)) \
191 #define EXPECT_GT(LHS, RHS) \
192 llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_GT, (LHS), \
193 (RHS), #LHS, #RHS, __FILE__, __LINE__)
194 #define ASSERT_GT(LHS, RHS) \
195 if (!EXPECT_GT(LHS, RHS)) \
198 #define EXPECT_GE(LHS, RHS) \
199 llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_GE, (LHS), \
200 (RHS), #LHS, #RHS, __FILE__, __LINE__)
201 #define ASSERT_GE(LHS, RHS) \
202 if (!EXPECT_GE(LHS, RHS)) \
205 #define EXPECT_STREQ(LHS, RHS) \
206 llvm_libc::testing::Test::testStrEq(Ctx, (LHS), (RHS), #LHS, #RHS, __FILE__, \
208 #define ASSERT_STREQ(LHS, RHS) \
209 if (!EXPECT_STREQ(LHS, RHS)) \
212 #define EXPECT_STRNE(LHS, RHS) \
213 llvm_libc::testing::Test::testStrNe(Ctx, (LHS), (RHS), #LHS, #RHS, __FILE__, \
215 #define ASSERT_STRNE(LHS, RHS) \
216 if (!EXPECT_STRNE(LHS, RHS)) \