[RDF] Add RegisterRef::idx and make toUnitId constexpr
[llvm-project.git] / libc / test / UnitTest / LibcTest.cpp
blob4570fc2b0ab2fe3ad3c96dce5dae830baf816bb3
1 //===-- Implementation of the base class for libc unittests----------------===//
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 //===----------------------------------------------------------------------===//
9 #include "LibcTest.h"
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"
16 #if __STDC_HOSTED__
17 #include <time.h>
18 #else
19 static long clock() { return 0; }
20 #define CLOCKS_PER_SEC 1
21 #endif
23 namespace __llvm_libc {
24 namespace testing {
26 namespace internal {
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.
33 template <typename T>
34 cpp::enable_if_t<cpp::is_integral_v<T> && cpp::is_unsigned_v<T> &&
35 (sizeof(T) > sizeof(uint64_t)),
36 cpp::string>
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),
48 cpp::string>
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 {
61 if (Cond)
62 return true;
63 Ctx->markFail();
64 size_t OffsetLength = OpString.size() > 2 ? OpString.size() - 2 : 0;
65 cpp::string Offset(OffsetLength, ' ');
66 tlog << Loc;
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';
71 return false;
74 switch (Cond) {
75 case TestCond::EQ:
76 return ExplainDifference(LHS == RHS, "equal to");
77 case TestCond::NE:
78 return ExplainDifference(LHS != RHS, "not equal to");
79 case TestCond::LT:
80 return ExplainDifference(LHS < RHS, "less than");
81 case TestCond::LE:
82 return ExplainDifference(LHS <= RHS, "less than or equal to");
83 case TestCond::GT:
84 return ExplainDifference(LHS > RHS, "greater than");
85 case TestCond::GE:
86 return ExplainDifference(LHS >= RHS, "greater than or equal to");
90 } // namespace internal
92 Test *Test::Start = nullptr;
93 Test *Test::End = nullptr;
95 int argc = 0;
96 char **argv = nullptr;
97 char **envp = nullptr;
99 using internal::RunContext;
101 void Test::addTest(Test *T) {
102 if (End == nullptr) {
103 Start = T;
104 End = T;
105 return;
108 End->Next = T;
109 End = T;
112 int Test::runTests(const char *TestFilter) {
113 int TestCount = 0;
114 int FailCount = 0;
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)) {
122 continue;
124 tlog << GREEN << "[ RUN ] " << RESET << TestName << '\n';
125 [[maybe_unused]] const auto start_time = clock();
126 RunContext Ctx;
127 T->SetUp();
128 T->setContext(&Ctx);
129 T->Run();
130 T->TearDown();
131 [[maybe_unused]] const auto end_time = clock();
132 switch (Ctx.status()) {
133 case RunContext::RunResult::Fail:
134 tlog << RED << "[ FAILED ] " << RESET << TestName << '\n';
135 ++FailCount;
136 break;
137 case RunContext::RunResult::Pass:
138 tlog << GREEN << "[ OK ] " << RESET << TestName;
139 #if __STDC_HOSTED__
140 tlog << " (took ";
141 if (start_time > end_time) {
142 tlog << "unknown - try rerunning)\n";
143 } else {
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";
148 #else
149 tlog << '\n';
150 #endif
151 break;
153 ++TestCount;
156 if (TestCount > 0) {
157 tlog << "Ran " << TestCount << " tests. "
158 << " PASS: " << TestCount - FailCount << ' ' << " FAIL: " << FailCount
159 << '\n';
160 } else {
161 tlog << "No tests run.\n";
162 if (TestFilter) {
163 tlog << "No matching test for " << TestFilter << '\n';
167 return FailCount > 0 || TestCount == 0 ? 1 : 0;
170 namespace internal {
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,
191 Location Loc);
193 template bool test<unsigned short>(RunContext *Ctx, TestCond Cond,
194 unsigned short LHS, unsigned short RHS,
195 const char *LHSStr, const char *RHSStr,
196 Location Loc);
198 template bool test<unsigned int>(RunContext *Ctx, TestCond Cond,
199 unsigned int LHS, unsigned int RHS,
200 const char *LHSStr, const char *RHSStr,
201 Location Loc);
203 template bool test<unsigned long>(RunContext *Ctx, TestCond Cond,
204 unsigned long LHS, unsigned long RHS,
205 const char *LHSStr, const char *RHSStr,
206 Location Loc);
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,
215 Location Loc);
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
220 // UInt128.
221 #ifdef __SIZEOF_INT128__
222 // When builtin __uint128_t type is available, include its specialization
223 // also.
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);
227 #endif
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,
232 const char *LHSStr,
233 const char *RHSStr,
234 Location Loc);
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,
239 const char *LHSStr,
240 const char *RHSStr,
241 Location Loc);
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,
246 const char *LHSStr,
247 const char *RHSStr,
248 Location Loc);
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,
253 const char *LHSStr,
254 const char *RHSStr,
255 Location Loc);
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,
260 Location Loc);
262 template bool test<__llvm_libc::cpp::string>(RunContext *Ctx, TestCond Cond,
263 __llvm_libc::cpp::string LHS,
264 __llvm_libc::cpp::string RHS,
265 const char *LHSStr,
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) {
286 if (MatchResult)
287 return true;
289 Ctx->markFail();
290 if (!Matcher.is_silent()) {
291 tlog << Loc;
292 tlog << "Failed to match " << LHSStr << " against " << RHSStr << ".\n";
293 Matcher.explainError();
295 return false;
298 } // namespace testing
299 } // namespace __llvm_libc