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