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 //===----------------------------------------------------------------------===// 8 9 #include "LibcTest.h" 10 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" 15 16 #if __STDC_HOSTED__ 17 #include <time.h> 18 #elif defined(LIBC_TARGET_ARCH_IS_GPU) 19 #include "src/__support/GPU/utils.h" 20 static long clock() { return LIBC_NAMESPACE::gpu::fixed_frequency_clock(); } 21 #if defined(LIBC_TARGET_ARCH_IS_NVPTX) 22 #define CLOCKS_PER_SEC 1000000000UL 23 #else 24 // The AMDGPU loader needs to initialize this at runtime by querying the driver. 25 extern "C" [[gnu::visibility("protected")]] uint64_t 26 [[clang::address_space(4)]] LIBC_NAMESPACE_clock_freq; 27 #define CLOCKS_PER_SEC LIBC_NAMESPACE_clock_freq 28 #endif 29 #else 30 static long clock() { return 0; } 31 #define CLOCKS_PER_SEC 1 32 #endif 33 34 namespace LIBC_NAMESPACE { 35 namespace testing { 36 37 namespace internal { 38 39 TestLogger &operator<<(TestLogger &logger, Location Loc) { 40 return logger << Loc.file << ":" << Loc.line << ": FAILURE\n"; 41 } 42 43 // When the value is UInt128, __uint128_t or wider, show its hexadecimal 44 // digits. 45 template <typename T> 46 cpp::enable_if_t<cpp::is_integral_v<T> && (sizeof(T) > sizeof(uint64_t)), 47 cpp::string> 48 describeValue(T Value) { 49 static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); 50 const IntegerToString<T, radix::Hex::WithPrefix> buffer(Value); 51 return buffer.view(); 52 } 53 54 // When the value is of a standard integral type, just display it as normal. 55 template <typename ValType> 56 cpp::enable_if_t<cpp::is_integral_v<ValType> && 57 sizeof(ValType) <= sizeof(uint64_t), 58 cpp::string> 59 describeValue(ValType Value) { 60 return cpp::to_string(Value); 61 } 62 63 cpp::string_view describeValue(const cpp::string &Value) { return Value; } 64 cpp::string_view describeValue(cpp::string_view Value) { return Value; } 65 66 template <typename ValType> 67 bool test(RunContext *Ctx, TestCond Cond, ValType LHS, ValType RHS, 68 const char *LHSStr, const char *RHSStr, Location Loc) { 69 auto ExplainDifference = [=, &Ctx](bool Cond, 70 cpp::string_view OpString) -> bool { 71 if (Cond) 72 return true; 73 Ctx->markFail(); 74 size_t OffsetLength = OpString.size() > 2 ? OpString.size() - 2 : 0; 75 cpp::string Offset(OffsetLength, ' '); 76 tlog << Loc; 77 tlog << Offset << "Expected: " << LHSStr << '\n' 78 << Offset << "Which is: " << describeValue(LHS) << '\n' 79 << "To be " << OpString << ": " << RHSStr << '\n' 80 << Offset << "Which is: " << describeValue(RHS) << '\n'; 81 return false; 82 }; 83 84 switch (Cond) { 85 case TestCond::EQ: 86 return ExplainDifference(LHS == RHS, "equal to"); 87 case TestCond::NE: 88 return ExplainDifference(LHS != RHS, "not equal to"); 89 case TestCond::LT: 90 return ExplainDifference(LHS < RHS, "less than"); 91 case TestCond::LE: 92 return ExplainDifference(LHS <= RHS, "less than or equal to"); 93 case TestCond::GT: 94 return ExplainDifference(LHS > RHS, "greater than"); 95 case TestCond::GE: 96 return ExplainDifference(LHS >= RHS, "greater than or equal to"); 97 } 98 __builtin_unreachable(); 99 } 100 101 } // namespace internal 102 103 Test *Test::Start = nullptr; 104 Test *Test::End = nullptr; 105 106 int argc = 0; 107 char **argv = nullptr; 108 char **envp = nullptr; 109 110 using internal::RunContext; 111 112 void Test::addTest(Test *T) { 113 if (End == nullptr) { 114 Start = T; 115 End = T; 116 return; 117 } 118 119 End->Next = T; 120 End = T; 121 } 122 123 int Test::runTests(const char *TestFilter) { 124 int TestCount = 0; 125 int FailCount = 0; 126 for (Test *T = Start; T != nullptr; T = T->Next) { 127 const char *TestName = T->getName(); 128 cpp::string StrTestName(TestName); 129 constexpr auto GREEN = "\033[32m"; 130 constexpr auto RED = "\033[31m"; 131 constexpr auto RESET = "\033[0m"; 132 if ((TestFilter != nullptr) && (StrTestName != TestFilter)) { 133 continue; 134 } 135 tlog << GREEN << "[ RUN ] " << RESET << TestName << '\n'; 136 [[maybe_unused]] const auto start_time = clock(); 137 RunContext Ctx; 138 T->SetUp(); 139 T->setContext(&Ctx); 140 T->Run(); 141 T->TearDown(); 142 [[maybe_unused]] const auto end_time = clock(); 143 switch (Ctx.status()) { 144 case RunContext::RunResult::Fail: 145 tlog << RED << "[ FAILED ] " << RESET << TestName << '\n'; 146 ++FailCount; 147 break; 148 case RunContext::RunResult::Pass: 149 tlog << GREEN << "[ OK ] " << RESET << TestName; 150 #if __STDC_HOSTED__ || defined(LIBC_TARGET_ARCH_IS_GPU) 151 tlog << " (took "; 152 if (start_time > end_time) { 153 tlog << "unknown - try rerunning)\n"; 154 } else { 155 const auto duration = end_time - start_time; 156 const uint64_t duration_ms = (duration * 1000) / CLOCKS_PER_SEC; 157 const uint64_t duration_us = (duration * 1000 * 1000) / CLOCKS_PER_SEC; 158 const uint64_t duration_ns = 159 (duration * 1000 * 1000 * 1000) / CLOCKS_PER_SEC; 160 if (duration_ms != 0) 161 tlog << duration_ms << " ms)\n"; 162 else if (duration_us != 0) 163 tlog << duration_us << " us)\n"; 164 else 165 tlog << duration_ns << " ns)\n"; 166 } 167 #else 168 tlog << '\n'; 169 #endif 170 break; 171 } 172 ++TestCount; 173 } 174 175 if (TestCount > 0) { 176 tlog << "Ran " << TestCount << " tests. " 177 << " PASS: " << TestCount - FailCount << ' ' << " FAIL: " << FailCount 178 << '\n'; 179 } else { 180 tlog << "No tests run.\n"; 181 if (TestFilter) { 182 tlog << "No matching test for " << TestFilter << '\n'; 183 } 184 } 185 186 return FailCount > 0 || TestCount == 0 ? 1 : 0; 187 } 188 189 namespace internal { 190 191 template bool test<char>(RunContext *Ctx, TestCond Cond, char LHS, char RHS, 192 const char *LHSStr, const char *RHSStr, Location Loc); 193 194 template bool test<short>(RunContext *Ctx, TestCond Cond, short LHS, short RHS, 195 const char *LHSStr, const char *RHSStr, Location Loc); 196 197 template bool test<int>(RunContext *Ctx, TestCond Cond, int LHS, int RHS, 198 const char *LHSStr, const char *RHSStr, Location Loc); 199 200 template bool test<long>(RunContext *Ctx, TestCond Cond, long LHS, long RHS, 201 const char *LHSStr, const char *RHSStr, Location Loc); 202 203 template bool test<long long>(RunContext *Ctx, TestCond Cond, long long LHS, 204 long long RHS, const char *LHSStr, 205 const char *RHSStr, Location Loc); 206 207 template bool test<unsigned char>(RunContext *Ctx, TestCond Cond, 208 unsigned char LHS, unsigned char RHS, 209 const char *LHSStr, const char *RHSStr, 210 Location Loc); 211 212 template bool test<unsigned short>(RunContext *Ctx, TestCond Cond, 213 unsigned short LHS, unsigned short RHS, 214 const char *LHSStr, const char *RHSStr, 215 Location Loc); 216 217 template bool test<unsigned int>(RunContext *Ctx, TestCond Cond, 218 unsigned int LHS, unsigned int RHS, 219 const char *LHSStr, const char *RHSStr, 220 Location Loc); 221 222 template bool test<unsigned long>(RunContext *Ctx, TestCond Cond, 223 unsigned long LHS, unsigned long RHS, 224 const char *LHSStr, const char *RHSStr, 225 Location Loc); 226 227 template bool test<bool>(RunContext *Ctx, TestCond Cond, bool LHS, bool RHS, 228 const char *LHSStr, const char *RHSStr, Location Loc); 229 230 template bool test<unsigned long long>(RunContext *Ctx, TestCond Cond, 231 unsigned long long LHS, 232 unsigned long long RHS, 233 const char *LHSStr, const char *RHSStr, 234 Location Loc); 235 236 // We cannot just use a single UInt128 specialization as that resolves to only 237 // one type, UInt<128> or __uint128_t. We want both overloads as we want to 238 // be able to unittest UInt<128> on platforms where UInt128 resolves to 239 // UInt128. 240 #ifdef __SIZEOF_INT128__ 241 // When builtin __uint128_t type is available, include its specialization 242 // also. 243 template bool test<__uint128_t>(RunContext *Ctx, TestCond Cond, __uint128_t LHS, 244 __uint128_t RHS, const char *LHSStr, 245 const char *RHSStr, Location Loc); 246 #endif 247 248 template bool test<LIBC_NAMESPACE::cpp::Int<128>>( 249 RunContext *Ctx, TestCond Cond, LIBC_NAMESPACE::cpp::Int<128> LHS, 250 LIBC_NAMESPACE::cpp::Int<128> RHS, const char *LHSStr, const char *RHSStr, 251 Location Loc); 252 253 template bool test<LIBC_NAMESPACE::cpp::UInt<128>>( 254 RunContext *Ctx, TestCond Cond, LIBC_NAMESPACE::cpp::UInt<128> LHS, 255 LIBC_NAMESPACE::cpp::UInt<128> RHS, const char *LHSStr, const char *RHSStr, 256 Location Loc); 257 258 template bool test<LIBC_NAMESPACE::cpp::UInt<192>>( 259 RunContext *Ctx, TestCond Cond, LIBC_NAMESPACE::cpp::UInt<192> LHS, 260 LIBC_NAMESPACE::cpp::UInt<192> RHS, const char *LHSStr, const char *RHSStr, 261 Location Loc); 262 263 template bool test<LIBC_NAMESPACE::cpp::UInt<256>>( 264 RunContext *Ctx, TestCond Cond, LIBC_NAMESPACE::cpp::UInt<256> LHS, 265 LIBC_NAMESPACE::cpp::UInt<256> RHS, const char *LHSStr, const char *RHSStr, 266 Location Loc); 267 268 template bool test<LIBC_NAMESPACE::cpp::UInt<320>>( 269 RunContext *Ctx, TestCond Cond, LIBC_NAMESPACE::cpp::UInt<320> LHS, 270 LIBC_NAMESPACE::cpp::UInt<320> RHS, const char *LHSStr, const char *RHSStr, 271 Location Loc); 272 273 template bool test<LIBC_NAMESPACE::cpp::string_view>( 274 RunContext *Ctx, TestCond Cond, LIBC_NAMESPACE::cpp::string_view LHS, 275 LIBC_NAMESPACE::cpp::string_view RHS, const char *LHSStr, 276 const char *RHSStr, Location Loc); 277 278 template bool test<LIBC_NAMESPACE::cpp::string>(RunContext *Ctx, TestCond Cond, 279 LIBC_NAMESPACE::cpp::string LHS, 280 LIBC_NAMESPACE::cpp::string RHS, 281 const char *LHSStr, 282 const char *RHSStr, 283 Location Loc); 284 285 } // namespace internal 286 287 bool Test::testStrEq(const char *LHS, const char *RHS, const char *LHSStr, 288 const char *RHSStr, internal::Location Loc) { 289 return internal::test( 290 Ctx, TestCond::EQ, LHS ? cpp::string_view(LHS) : cpp::string_view(), 291 RHS ? cpp::string_view(RHS) : cpp::string_view(), LHSStr, RHSStr, Loc); 292 } 293 294 bool Test::testStrNe(const char *LHS, const char *RHS, const char *LHSStr, 295 const char *RHSStr, internal::Location Loc) { 296 return internal::test( 297 Ctx, TestCond::NE, LHS ? cpp::string_view(LHS) : cpp::string_view(), 298 RHS ? cpp::string_view(RHS) : cpp::string_view(), LHSStr, RHSStr, Loc); 299 } 300 301 bool Test::testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr, 302 const char *RHSStr, internal::Location Loc) { 303 if (MatchResult) 304 return true; 305 306 Ctx->markFail(); 307 if (!Matcher.is_silent()) { 308 tlog << Loc; 309 tlog << "Failed to match " << LHSStr << " against " << RHSStr << ".\n"; 310 Matcher.explainError(); 311 } 312 return false; 313 } 314 315 } // namespace testing 316 } // namespace LIBC_NAMESPACE 317