1 //===-- Implementation of the base class for libc unittests----------------===//
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 //===----------------------------------------------------------------------===//
11 #include "src/__support/CPP/string.h"
12 #include "src/__support/CPP/string_view.h"
13 #include "src/__support/UInt128.h"
14 #include "test/UnitTest/TestLogger.h"
19 static long clock() { return 0; }
20 #define CLOCKS_PER_SEC 1
23 namespace __llvm_libc
{
28 TestLogger
&operator<<(TestLogger
&logger
, Location Loc
) {
29 return logger
<< Loc
.file
<< ":" << Loc
.line
<< ": FAILURE\n";
32 // When the value is UInt128, __uint128_t or wider, show its hexadecimal digits.
34 cpp::enable_if_t
<cpp::is_integral_v
<T
> && cpp::is_unsigned_v
<T
> &&
35 (sizeof(T
) > sizeof(uint64_t)),
37 describeValue(T Value
) {
38 static_assert(sizeof(T
) % 8 == 0, "Unsupported size of UInt");
39 char buf
[IntegerToString::hex_bufsize
<T
>()];
40 IntegerToString::hex(Value
, buf
, false);
41 return "0x" + cpp::string(buf
, sizeof(buf
));
44 // When the value is of a standard integral type, just display it as normal.
45 template <typename ValType
>
46 cpp::enable_if_t
<cpp::is_integral_v
<ValType
> &&
47 sizeof(ValType
) <= sizeof(uint64_t),
49 describeValue(ValType Value
) {
50 return cpp::to_string(Value
);
53 cpp::string_view
describeValue(const cpp::string
&Value
) { return Value
; }
54 cpp::string_view
describeValue(cpp::string_view Value
) { return Value
; }
56 template <typename ValType
>
57 bool test(RunContext
*Ctx
, TestCond Cond
, ValType LHS
, ValType RHS
,
58 const char *LHSStr
, const char *RHSStr
, Location Loc
) {
59 auto ExplainDifference
= [=, &Ctx
](bool Cond
,
60 cpp::string_view OpString
) -> bool {
64 size_t OffsetLength
= OpString
.size() > 2 ? OpString
.size() - 2 : 0;
65 cpp::string
Offset(OffsetLength
, ' ');
67 tlog
<< Offset
<< "Expected: " << LHSStr
<< '\n'
68 << Offset
<< "Which is: " << describeValue(LHS
) << '\n'
69 << "To be " << OpString
<< ": " << RHSStr
<< '\n'
70 << Offset
<< "Which is: " << describeValue(RHS
) << '\n';
76 return ExplainDifference(LHS
== RHS
, "equal to");
78 return ExplainDifference(LHS
!= RHS
, "not equal to");
80 return ExplainDifference(LHS
< RHS
, "less than");
82 return ExplainDifference(LHS
<= RHS
, "less than or equal to");
84 return ExplainDifference(LHS
> RHS
, "greater than");
86 return ExplainDifference(LHS
>= RHS
, "greater than or equal to");
90 } // namespace internal
92 Test
*Test::Start
= nullptr;
93 Test
*Test::End
= nullptr;
96 char **argv
= nullptr;
97 char **envp
= nullptr;
99 using internal::RunContext
;
101 void Test::addTest(Test
*T
) {
102 if (End
== nullptr) {
112 int Test::runTests(const char *TestFilter
) {
115 for (Test
*T
= Start
; T
!= nullptr; T
= T
->Next
) {
116 const char *TestName
= T
->getName();
117 cpp::string
StrTestName(TestName
);
118 constexpr auto GREEN
= "\033[32m";
119 constexpr auto RED
= "\033[31m";
120 constexpr auto RESET
= "\033[0m";
121 if ((TestFilter
!= nullptr) && (StrTestName
!= TestFilter
)) {
124 tlog
<< GREEN
<< "[ RUN ] " << RESET
<< TestName
<< '\n';
125 [[maybe_unused
]] const auto start_time
= clock();
131 [[maybe_unused
]] const auto end_time
= clock();
132 switch (Ctx
.status()) {
133 case RunContext::RunResult::Fail
:
134 tlog
<< RED
<< "[ FAILED ] " << RESET
<< TestName
<< '\n';
137 case RunContext::RunResult::Pass
:
138 tlog
<< GREEN
<< "[ OK ] " << RESET
<< TestName
;
141 if (start_time
> end_time
) {
142 tlog
<< "unknown - try rerunning)\n";
144 const auto duration
= end_time
- start_time
;
145 const uint64_t duration_ms
= duration
* 1000 / CLOCKS_PER_SEC
;
146 tlog
<< duration_ms
<< " ms)\n";
157 tlog
<< "Ran " << TestCount
<< " tests. "
158 << " PASS: " << TestCount
- FailCount
<< ' ' << " FAIL: " << FailCount
161 tlog
<< "No tests run.\n";
163 tlog
<< "No matching test for " << TestFilter
<< '\n';
167 return FailCount
> 0 || TestCount
== 0 ? 1 : 0;
172 template bool test
<char>(RunContext
*Ctx
, TestCond Cond
, char LHS
, char RHS
,
173 const char *LHSStr
, const char *RHSStr
, Location Loc
);
175 template bool test
<short>(RunContext
*Ctx
, TestCond Cond
, short LHS
, short RHS
,
176 const char *LHSStr
, const char *RHSStr
, Location Loc
);
178 template bool test
<int>(RunContext
*Ctx
, TestCond Cond
, int LHS
, int RHS
,
179 const char *LHSStr
, const char *RHSStr
, Location Loc
);
181 template bool test
<long>(RunContext
*Ctx
, TestCond Cond
, long LHS
, long RHS
,
182 const char *LHSStr
, const char *RHSStr
, Location Loc
);
184 template bool test
<long long>(RunContext
*Ctx
, TestCond Cond
, long long LHS
,
185 long long RHS
, const char *LHSStr
,
186 const char *RHSStr
, Location Loc
);
188 template bool test
<unsigned char>(RunContext
*Ctx
, TestCond Cond
,
189 unsigned char LHS
, unsigned char RHS
,
190 const char *LHSStr
, const char *RHSStr
,
193 template bool test
<unsigned short>(RunContext
*Ctx
, TestCond Cond
,
194 unsigned short LHS
, unsigned short RHS
,
195 const char *LHSStr
, const char *RHSStr
,
198 template bool test
<unsigned int>(RunContext
*Ctx
, TestCond Cond
,
199 unsigned int LHS
, unsigned int RHS
,
200 const char *LHSStr
, const char *RHSStr
,
203 template bool test
<unsigned long>(RunContext
*Ctx
, TestCond Cond
,
204 unsigned long LHS
, unsigned long RHS
,
205 const char *LHSStr
, const char *RHSStr
,
208 template bool test
<bool>(RunContext
*Ctx
, TestCond Cond
, bool LHS
, bool RHS
,
209 const char *LHSStr
, const char *RHSStr
, Location Loc
);
211 template bool test
<unsigned long long>(RunContext
*Ctx
, TestCond Cond
,
212 unsigned long long LHS
,
213 unsigned long long RHS
,
214 const char *LHSStr
, const char *RHSStr
,
217 // We cannot just use a single UInt128 specialization as that resolves to only
218 // one type, UInt<128> or __uint128_t. We want both overloads as we want to
219 // be able to unittest UInt<128> on platforms where UInt128 resolves to
221 #ifdef __SIZEOF_INT128__
222 // When builtin __uint128_t type is available, include its specialization
224 template bool test
<__uint128_t
>(RunContext
*Ctx
, TestCond Cond
, __uint128_t LHS
,
225 __uint128_t RHS
, const char *LHSStr
,
226 const char *RHSStr
, Location Loc
);
229 template bool test
<__llvm_libc::cpp::UInt
<128>>(RunContext
*Ctx
, TestCond Cond
,
230 __llvm_libc::cpp::UInt
<128> LHS
,
231 __llvm_libc::cpp::UInt
<128> RHS
,
236 template bool test
<__llvm_libc::cpp::UInt
<192>>(RunContext
*Ctx
, TestCond Cond
,
237 __llvm_libc::cpp::UInt
<192> LHS
,
238 __llvm_libc::cpp::UInt
<192> RHS
,
243 template bool test
<__llvm_libc::cpp::UInt
<256>>(RunContext
*Ctx
, TestCond Cond
,
244 __llvm_libc::cpp::UInt
<256> LHS
,
245 __llvm_libc::cpp::UInt
<256> RHS
,
250 template bool test
<__llvm_libc::cpp::UInt
<320>>(RunContext
*Ctx
, TestCond Cond
,
251 __llvm_libc::cpp::UInt
<320> LHS
,
252 __llvm_libc::cpp::UInt
<320> RHS
,
257 template bool test
<__llvm_libc::cpp::string_view
>(
258 RunContext
*Ctx
, TestCond Cond
, __llvm_libc::cpp::string_view LHS
,
259 __llvm_libc::cpp::string_view RHS
, const char *LHSStr
, const char *RHSStr
,
262 template bool test
<__llvm_libc::cpp::string
>(RunContext
*Ctx
, TestCond Cond
,
263 __llvm_libc::cpp::string LHS
,
264 __llvm_libc::cpp::string RHS
,
266 const char *RHSStr
, Location Loc
);
268 } // namespace internal
270 bool Test::testStrEq(const char *LHS
, const char *RHS
, const char *LHSStr
,
271 const char *RHSStr
, internal::Location Loc
) {
272 return internal::test(
273 Ctx
, TestCond::EQ
, LHS
? cpp::string_view(LHS
) : cpp::string_view(),
274 RHS
? cpp::string_view(RHS
) : cpp::string_view(), LHSStr
, RHSStr
, Loc
);
277 bool Test::testStrNe(const char *LHS
, const char *RHS
, const char *LHSStr
,
278 const char *RHSStr
, internal::Location Loc
) {
279 return internal::test(
280 Ctx
, TestCond::NE
, LHS
? cpp::string_view(LHS
) : cpp::string_view(),
281 RHS
? cpp::string_view(RHS
) : cpp::string_view(), LHSStr
, RHSStr
, Loc
);
284 bool Test::testMatch(bool MatchResult
, MatcherBase
&Matcher
, const char *LHSStr
,
285 const char *RHSStr
, internal::Location Loc
) {
290 if (!Matcher
.is_silent()) {
292 tlog
<< "Failed to match " << LHSStr
<< " against " << RHSStr
<< ".\n";
293 Matcher
.explainError();
298 } // namespace testing
299 } // namespace __llvm_libc