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 #ifndef LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H
10 #define LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H
12 // This is defined as a simple macro in test.h so that it exists for platforms
13 // that don't use our test infrastructure. It's defined as a proper function
15 #ifdef libc_make_test_file_path
16 #undef libc_make_test_file_path
17 #endif // libc_make_test_file_path
19 // This is defined as a macro here to avoid namespace issues.
20 #define libc_make_test_file_path(file_name) \
21 (LIBC_NAMESPACE::testing::libc_make_test_file_path_func(file_name))
23 // This file can only include headers from src/__support/ or test/UnitTest. No
24 // other headers should be included.
26 #include "PlatformDefs.h"
28 #include "src/__support/CPP/string.h"
29 #include "src/__support/CPP/string_view.h"
30 #include "src/__support/CPP/type_traits.h"
31 #include "src/__support/c_string.h"
32 #include "test/UnitTest/ExecuteFunction.h"
33 #include "test/UnitTest/TestLogger.h"
35 namespace LIBC_NAMESPACE
{
38 // Only the following conditions are supported. Notice that we do not have
39 // a TRUE or FALSE condition. That is because, C library functions do not
40 // return boolean values, but use integral return values to indicate true or
41 // false conditions. Hence, it is more appropriate to use the other comparison
42 // conditions for such cases.
43 enum class TestCond
{ EQ
, NE
, LT
, LE
, GT
, GE
};
46 virtual ~MatcherBase() {}
47 virtual void explainError() { tlog
<< "unknown error\n"; }
48 // Override and return true to skip `explainError` step.
49 virtual bool is_silent() const { return false; }
52 template <typename T
> struct Matcher
: public MatcherBase
{
53 bool match(const T
&t
);
58 // A simple location object to allow consistent passing of __FILE__ and
61 Location(const char *file
, int line
) : file(file
), line(line
) {}
66 // Supports writing a failing Location to tlog.
67 TestLogger
&operator<<(TestLogger
&logger
, Location Loc
);
69 #define LIBC_TEST_LOC_() \
70 LIBC_NAMESPACE::testing::internal::Location(__FILE__, __LINE__)
72 // Object to forward custom logging after the EXPECT / ASSERT macros.
74 template <typename T
> Message
&operator<<(T value
) {
80 // A trivial object to catch the Message, this enables custom logging and
81 // returning from the test function, see LIBC_TEST_SCAFFOLDING_ below.
83 void operator=(Message msg
) {}
87 enum class RunResult
: bool { Pass
, Fail
};
89 RunResult
status() const { return Status
; }
91 void markFail() { Status
= RunResult::Fail
; }
94 RunResult Status
= RunResult::Pass
;
97 template <typename ValType
>
98 bool test(RunContext
*Ctx
, TestCond Cond
, ValType LHS
, ValType RHS
,
99 const char *LHSStr
, const char *RHSStr
, Location Loc
);
101 } // namespace internal
103 // NOTE: One should not create instances and call methods on them directly. One
104 // should use the macros TEST or TEST_F to write test cases.
106 Test
*Next
= nullptr;
107 internal::RunContext
*Ctx
= nullptr;
109 void setContext(internal::RunContext
*C
) { Ctx
= C
; }
113 virtual void SetUp() {}
114 virtual void TearDown() {}
116 static int runTests(const char *);
119 static void addTest(Test
*T
);
121 // We make use of a template function, with |LHS| and |RHS| as explicit
122 // parameters, for enhanced type checking. Other gtest like unittest
123 // frameworks have a similar function which takes a boolean argument
124 // instead of the explicit |LHS| and |RHS| arguments. This boolean argument
125 // is the result of the |Cond| operation on |LHS| and |RHS|. Though not bad,
126 // |Cond| on mismatched |LHS| and |RHS| types can potentially succeed because
127 // of type promotion.
128 template <typename ValType
,
129 cpp::enable_if_t
<cpp::is_integral_v
<ValType
>, int> = 0>
130 bool test(TestCond Cond
, ValType LHS
, ValType RHS
, const char *LHSStr
,
131 const char *RHSStr
, internal::Location Loc
) {
132 return internal::test(Ctx
, Cond
, LHS
, RHS
, LHSStr
, RHSStr
, Loc
);
135 template <typename ValType
,
136 cpp::enable_if_t
<cpp::is_enum_v
<ValType
>, int> = 0>
137 bool test(TestCond Cond
, ValType LHS
, ValType RHS
, const char *LHSStr
,
138 const char *RHSStr
, internal::Location Loc
) {
139 return internal::test(Ctx
, Cond
, (long long)LHS
, (long long)RHS
, LHSStr
,
143 template <typename ValType
,
144 cpp::enable_if_t
<cpp::is_pointer_v
<ValType
>, ValType
> = nullptr>
145 bool test(TestCond Cond
, ValType LHS
, ValType RHS
, const char *LHSStr
,
146 const char *RHSStr
, internal::Location Loc
) {
147 return internal::test(Ctx
, Cond
, (unsigned long long)LHS
,
148 (unsigned long long)RHS
, LHSStr
, RHSStr
, Loc
);
154 cpp::is_same_v
<ValType
, LIBC_NAMESPACE::cpp::string_view
>, int> = 0>
155 bool test(TestCond Cond
, ValType LHS
, ValType RHS
, const char *LHSStr
,
156 const char *RHSStr
, internal::Location Loc
) {
157 return internal::test(Ctx
, Cond
, LHS
, RHS
, LHSStr
, RHSStr
, Loc
);
160 template <typename ValType
,
162 cpp::is_same_v
<ValType
, LIBC_NAMESPACE::cpp::string
>, int> = 0>
163 bool test(TestCond Cond
, ValType LHS
, ValType RHS
, const char *LHSStr
,
164 const char *RHSStr
, internal::Location Loc
) {
165 return internal::test(Ctx
, Cond
, LHS
, RHS
, LHSStr
, RHSStr
, Loc
);
168 bool testStrEq(const char *LHS
, const char *RHS
, const char *LHSStr
,
169 const char *RHSStr
, internal::Location Loc
);
171 bool testStrNe(const char *LHS
, const char *RHS
, const char *LHSStr
,
172 const char *RHSStr
, internal::Location Loc
);
174 bool testMatch(bool MatchResult
, MatcherBase
&Matcher
, const char *LHSStr
,
175 const char *RHSStr
, internal::Location Loc
);
177 template <typename MatcherT
, typename ValType
>
178 bool matchAndExplain(MatcherT
&&Matcher
, ValType Value
,
179 const char *MatcherStr
, const char *ValueStr
,
180 internal::Location Loc
) {
181 return testMatch(Matcher
.match(Value
), Matcher
, ValueStr
, MatcherStr
, Loc
);
184 bool testProcessExits(testutils::FunctionCaller
*Func
, int ExitCode
,
185 const char *LHSStr
, const char *RHSStr
,
186 internal::Location Loc
);
188 bool testProcessKilled(testutils::FunctionCaller
*Func
, int Signal
,
189 const char *LHSStr
, const char *RHSStr
,
190 internal::Location Loc
);
192 template <typename Func
> testutils::FunctionCaller
*createCallable(Func f
) {
193 struct Callable
: public testutils::FunctionCaller
{
195 Callable(Func f
) : f(f
) {}
196 void operator()() override
{ f(); }
199 return new Callable(f
);
203 virtual void Run() = 0;
204 virtual const char *getName() const = 0;
216 constexpr bool same_prefix(char const *lhs
, char const *rhs
, int const len
) {
217 for (int i
= 0; (*lhs
|| *rhs
) && (i
< len
); ++lhs
, ++rhs
, ++i
)
223 constexpr bool valid_prefix(char const *lhs
) {
224 return same_prefix(lhs
, "LlvmLibc", 8);
227 // 'str' is a null terminated string of the form
228 // "const char *LIBC_NAMESPACE::testing::internal::GetTypeName() [ParamType =
229 // XXX]" We return the substring that start at character '[' or a default
231 constexpr char const *GetPrettyFunctionParamType(char const *str
) {
232 for (const char *ptr
= str
; *ptr
!= '\0'; ++ptr
)
235 return "UNSET : declare with REGISTER_TYPE_NAME";
238 // This function recovers ParamType at compile time by using __PRETTY_FUNCTION__
239 // It can be customized by using the REGISTER_TYPE_NAME macro below.
240 template <typename ParamType
> static constexpr const char *GetTypeName() {
241 return GetPrettyFunctionParamType(__PRETTY_FUNCTION__
);
244 template <typename T
>
245 static inline void GenerateName(char *buffer
, int buffer_size
,
246 const char *prefix
) {
247 if (buffer_size
== 0)
250 // Make sure string is null terminated.
252 buffer
[buffer_size
] = '\0';
254 const auto AppendChar
= [&](char c
) {
255 if (buffer_size
> 0) {
261 const auto AppendStr
= [&](const char *str
) {
262 for (; str
&& *str
!= '\0'; ++str
)
268 AppendStr(GetTypeName
<T
>());
272 // TestCreator implements a linear hierarchy of test instances, effectively
273 // instanciating all tests with Types in a single object.
274 template <template <typename
> class TemplatedTestClass
, typename
... Types
>
277 template <template <typename
> class TemplatedTestClass
, typename Head
,
279 struct TestCreator
<TemplatedTestClass
, Head
, Tail
...>
280 : private TestCreator
<TemplatedTestClass
, Tail
...> {
281 TemplatedTestClass
<Head
> instance
;
284 template <template <typename
> class TemplatedTestClass
>
285 struct TestCreator
<TemplatedTestClass
> {};
287 // A type list to declare the set of types to instantiate the tests with.
288 template <typename
... Types
> struct TypeList
{
289 template <template <typename
> class TemplatedTestClass
> struct Tests
{
290 using type
= TestCreator
<TemplatedTestClass
, Types
...>;
294 } // namespace internal
296 // Make TypeList visible in LIBC_NAMESPACE::testing.
297 template <typename
... Types
> using TypeList
= internal::TypeList
<Types
...>;
299 CString
libc_make_test_file_path_func(const char *file_name
);
301 } // namespace testing
302 } // namespace LIBC_NAMESPACE
304 // For TYPED_TEST and TYPED_TEST_F below we need to display which type was used
305 // to run the test. The default will return the fully qualified canonical type
306 // but it can be difficult to read. We provide the following macro to allow the
307 // client to register the type name as they see it in the code.
308 #define REGISTER_TYPE_NAME(TYPE) \
310 constexpr const char * \
311 LIBC_NAMESPACE::testing::internal::GetTypeName<TYPE>() { \
312 return "[ParamType = " #TYPE "]"; \
315 #define TYPED_TEST(SuiteName, TestName, TypeList) \
317 LIBC_NAMESPACE::testing::internal::valid_prefix(#SuiteName), \
318 "All LLVM-libc TYPED_TEST suite names must start with 'LlvmLibc'."); \
319 template <typename T> \
320 class SuiteName##_##TestName : public LIBC_NAMESPACE::testing::Test { \
322 using ParamType = T; \
324 SuiteName##_##TestName() { \
326 LIBC_NAMESPACE::testing::internal::GenerateName<T>( \
327 name, sizeof(name), #SuiteName "." #TestName); \
329 void Run() override; \
330 const char *getName() const override { return name; } \
332 TypeList::Tests<SuiteName##_##TestName>::type \
333 SuiteName##_##TestName##_Instance; \
334 template <typename T> void SuiteName##_##TestName<T>::Run()
336 #define TYPED_TEST_F(SuiteClass, TestName, TypeList) \
337 static_assert(LIBC_NAMESPACE::testing::internal::valid_prefix(#SuiteClass), \
338 "All LLVM-libc TYPED_TEST_F suite class names must start " \
339 "with 'LlvmLibc'."); \
340 template <typename T> class SuiteClass##_##TestName : public SuiteClass<T> { \
342 using ParamType = T; \
344 SuiteClass##_##TestName() { \
345 SuiteClass<T>::addTest(this); \
346 LIBC_NAMESPACE::testing::internal::GenerateName<T>( \
347 name, sizeof(name), #SuiteClass "." #TestName); \
349 void Run() override; \
350 const char *getName() const override { return name; } \
352 TypeList::Tests<SuiteClass##_##TestName>::type \
353 SuiteClass##_##TestName##_Instance; \
354 template <typename T> void SuiteClass##_##TestName<T>::Run()
356 #define TEST(SuiteName, TestName) \
357 static_assert(LIBC_NAMESPACE::testing::internal::valid_prefix(#SuiteName), \
358 "All LLVM-libc TEST suite names must start with 'LlvmLibc'."); \
359 class SuiteName##_##TestName : public LIBC_NAMESPACE::testing::Test { \
361 SuiteName##_##TestName() { addTest(this); } \
362 void Run() override; \
363 const char *getName() const override { return #SuiteName "." #TestName; } \
365 SuiteName##_##TestName SuiteName##_##TestName##_Instance; \
366 void SuiteName##_##TestName::Run()
368 #define TEST_F(SuiteClass, TestName) \
370 LIBC_NAMESPACE::testing::internal::valid_prefix(#SuiteClass), \
371 "All LLVM-libc TEST_F suite class names must start with 'LlvmLibc'."); \
372 class SuiteClass##_##TestName : public SuiteClass { \
374 SuiteClass##_##TestName() { addTest(this); } \
375 void Run() override; \
376 const char *getName() const override { return #SuiteClass "." #TestName; } \
378 SuiteClass##_##TestName SuiteClass##_##TestName##_Instance; \
379 void SuiteClass##_##TestName::Run()
381 // If RET_OR_EMPTY is the 'return' keyword we perform an early return which
382 // corresponds to an assert. If it is empty the execution continues, this
383 // corresponds to an expect.
385 // The 'else' clause must not be enclosed into braces so that the << operator
386 // can be used to fill the Message.
388 // TEST is usually implemented as a function performing checking logic and
389 // returning a boolean. This expression is responsible for logging the
390 // diagnostic in case of failure.
391 #define LIBC_TEST_SCAFFOLDING_(TEST, RET_OR_EMPTY) \
395 RET_OR_EMPTY LIBC_NAMESPACE::testing::internal::Failure() = \
396 LIBC_NAMESPACE::testing::internal::Message()
398 #define LIBC_TEST_BINOP_(COND, LHS, RHS, RET_OR_EMPTY) \
399 LIBC_TEST_SCAFFOLDING_(test(LIBC_NAMESPACE::testing::TestCond::COND, LHS, \
400 RHS, #LHS, #RHS, LIBC_TEST_LOC_()), \
403 ////////////////////////////////////////////////////////////////////////////////
404 // Binary operations corresponding to the TestCond enum.
406 #define EXPECT_EQ(LHS, RHS) LIBC_TEST_BINOP_(EQ, LHS, RHS, )
407 #define ASSERT_EQ(LHS, RHS) LIBC_TEST_BINOP_(EQ, LHS, RHS, return)
409 #define EXPECT_NE(LHS, RHS) LIBC_TEST_BINOP_(NE, LHS, RHS, )
410 #define ASSERT_NE(LHS, RHS) LIBC_TEST_BINOP_(NE, LHS, RHS, return)
412 #define EXPECT_LT(LHS, RHS) LIBC_TEST_BINOP_(LT, LHS, RHS, )
413 #define ASSERT_LT(LHS, RHS) LIBC_TEST_BINOP_(LT, LHS, RHS, return)
415 #define EXPECT_LE(LHS, RHS) LIBC_TEST_BINOP_(LE, LHS, RHS, )
416 #define ASSERT_LE(LHS, RHS) LIBC_TEST_BINOP_(LE, LHS, RHS, return)
418 #define EXPECT_GT(LHS, RHS) LIBC_TEST_BINOP_(GT, LHS, RHS, )
419 #define ASSERT_GT(LHS, RHS) LIBC_TEST_BINOP_(GT, LHS, RHS, return)
421 #define EXPECT_GE(LHS, RHS) LIBC_TEST_BINOP_(GE, LHS, RHS, )
422 #define ASSERT_GE(LHS, RHS) LIBC_TEST_BINOP_(GE, LHS, RHS, return)
424 ////////////////////////////////////////////////////////////////////////////////
425 // Boolean checks are handled as comparison to the true / false values.
427 #define EXPECT_TRUE(VAL) EXPECT_EQ(VAL, true)
428 #define ASSERT_TRUE(VAL) ASSERT_EQ(VAL, true)
430 #define EXPECT_FALSE(VAL) EXPECT_EQ(VAL, false)
431 #define ASSERT_FALSE(VAL) ASSERT_EQ(VAL, false)
433 ////////////////////////////////////////////////////////////////////////////////
436 #define LIBC_TEST_STR_(TEST_FUNC, LHS, RHS, RET_OR_EMPTY) \
437 LIBC_TEST_SCAFFOLDING_(TEST_FUNC(LHS, RHS, #LHS, #RHS, LIBC_TEST_LOC_()), \
440 #define EXPECT_STREQ(LHS, RHS) LIBC_TEST_STR_(testStrEq, LHS, RHS, )
441 #define ASSERT_STREQ(LHS, RHS) LIBC_TEST_STR_(testStrEq, LHS, RHS, return)
443 #define EXPECT_STRNE(LHS, RHS) LIBC_TEST_STR_(testStrNe, LHS, RHS, )
444 #define ASSERT_STRNE(LHS, RHS) LIBC_TEST_STR_(testStrNe, LHS, RHS, return)
446 ////////////////////////////////////////////////////////////////////////////////
447 // Subprocess checks.
449 #ifdef ENABLE_SUBPROCESS_TESTS
451 #define LIBC_TEST_PROCESS_(TEST_FUNC, FUNC, VALUE, RET_OR_EMPTY) \
452 LIBC_TEST_SCAFFOLDING_( \
453 TEST_FUNC(LIBC_NAMESPACE::testing::Test::createCallable(FUNC), VALUE, \
454 #FUNC, #VALUE, LIBC_TEST_LOC_()), \
457 #define EXPECT_EXITS(FUNC, EXIT) \
458 LIBC_TEST_PROCESS_(testProcessExits, FUNC, EXIT, )
459 #define ASSERT_EXITS(FUNC, EXIT) \
460 LIBC_TEST_PROCESS_(testProcessExits, FUNC, EXIT, return)
462 #define EXPECT_DEATH(FUNC, SIG) \
463 LIBC_TEST_PROCESS_(testProcessKilled, FUNC, SIG, )
464 #define ASSERT_DEATH(FUNC, SIG) \
465 LIBC_TEST_PROCESS_(testProcessKilled, FUNC, SIG, return)
467 #endif // ENABLE_SUBPROCESS_TESTS
469 ////////////////////////////////////////////////////////////////////////////////
470 // Custom matcher checks.
472 #define LIBC_TEST_MATCH_(MATCHER, MATCH, MATCHER_STR, MATCH_STR, RET_OR_EMPTY) \
473 LIBC_TEST_SCAFFOLDING_(matchAndExplain(MATCHER, MATCH, MATCHER_STR, \
474 MATCH_STR, LIBC_TEST_LOC_()), \
477 #define EXPECT_THAT(MATCH, MATCHER) \
478 LIBC_TEST_MATCH_(MATCHER, MATCH, #MATCHER, #MATCH, )
479 #define ASSERT_THAT(MATCH, MATCHER) \
480 LIBC_TEST_MATCH_(MATCHER, MATCH, #MATCHER, #MATCH, return)
482 #define WITH_SIGNAL(X) X
484 #endif // LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H