1af1315c2SSiva Chandra Reddy //===-- Implementation of the base class for libc unittests----------------===// 2af1315c2SSiva Chandra Reddy // 3af1315c2SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4af1315c2SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 5af1315c2SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6af1315c2SSiva Chandra Reddy // 7af1315c2SSiva Chandra Reddy //===----------------------------------------------------------------------===// 8af1315c2SSiva Chandra Reddy 9af1315c2SSiva Chandra Reddy #include "LibcTest.h" 10af1315c2SSiva Chandra Reddy 1173aab2f6Slntue #include "include/llvm-libc-macros/stdfix-macros.h" 12f5dcab0dSGuillaume Chatelet #include "src/__support/CPP/string.h" 13af1315c2SSiva Chandra Reddy #include "src/__support/CPP/string_view.h" 1482a4a416Slntue #include "src/__support/fixed_point/fx_rep.h" 155ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 1623c397c7SGuillaume Chatelet #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 1709efe848SGuillaume Chatelet #include "src/__support/uint128.h" 18f5dcab0dSGuillaume Chatelet #include "test/UnitTest/TestLogger.h" 19af1315c2SSiva Chandra Reddy 2004e066dfSGuillaume Chatelet #if __STDC_HOSTED__ 2104e066dfSGuillaume Chatelet #include <time.h> 22158d7b8cSJoseph Huber #define LIBC_TEST_USE_CLOCK 23158d7b8cSJoseph Huber #elif defined(TARGET_SUPPORTS_CLOCK) 24158d7b8cSJoseph Huber #include <time.h> 25158d7b8cSJoseph Huber 26158d7b8cSJoseph Huber #include "src/time/clock.h" 27158d7b8cSJoseph Huber extern "C" clock_t clock() noexcept { return LIBC_NAMESPACE::clock(); } 28158d7b8cSJoseph Huber #define LIBC_TEST_USE_CLOCK 2904e066dfSGuillaume Chatelet #endif 3004e066dfSGuillaume Chatelet 315ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 32af1315c2SSiva Chandra Reddy namespace testing { 33af1315c2SSiva Chandra Reddy 34af1315c2SSiva Chandra Reddy namespace internal { 35af1315c2SSiva Chandra Reddy 368e44b849SGuillaume Chatelet TestLogger &operator<<(TestLogger &logger, Location Loc) { 378e44b849SGuillaume Chatelet return logger << Loc.file << ":" << Loc.line << ": FAILURE\n"; 388e44b849SGuillaume Chatelet } 398e44b849SGuillaume Chatelet 409902fc8dSGuillaume Chatelet // When the value is UInt128, __uint128_t or wider, show its hexadecimal 419902fc8dSGuillaume Chatelet // digits. 42af1315c2SSiva Chandra Reddy template <typename T> 43245d669fSGuillaume Chatelet cpp::enable_if_t<(cpp::is_integral_v<T> && (sizeof(T) > sizeof(uint64_t))) || 446a8e6c9aSGuillaume Chatelet is_big_int_v<T>, 45b095aa3fSSiva Chandra Reddy cpp::string> 46b095aa3fSSiva Chandra Reddy describeValue(T Value) { 47b555912eSGuillaume Chatelet const IntegerToString<T, radix::Hex::WithPrefix> buffer(Value); 48b555912eSGuillaume Chatelet return buffer.view(); 49af1315c2SSiva Chandra Reddy } 50af1315c2SSiva Chandra Reddy 51b095aa3fSSiva Chandra Reddy // When the value is of a standard integral type, just display it as normal. 52245d669fSGuillaume Chatelet template <typename T> 53245d669fSGuillaume Chatelet cpp::enable_if_t<cpp::is_integral_v<T> && (sizeof(T) <= sizeof(uint64_t)), 54b095aa3fSSiva Chandra Reddy cpp::string> 55245d669fSGuillaume Chatelet describeValue(T Value) { 56f5dcab0dSGuillaume Chatelet return cpp::to_string(Value); 57af1315c2SSiva Chandra Reddy } 58af1315c2SSiva Chandra Reddy 5982a4a416Slntue #ifdef LIBC_COMPILER_HAS_FIXED_POINT 6082a4a416Slntue template <typename T> 6182a4a416Slntue cpp::enable_if_t<cpp::is_fixed_point_v<T>, cpp::string> describeValue(T Value) { 6282a4a416Slntue using FXRep = fixed_point::FXRep<T>; 6382a4a416Slntue using comp_t = typename FXRep::CompType; 6482a4a416Slntue 6582a4a416Slntue return cpp::to_string(cpp::bit_cast<comp_t>(Value)) + " * 2^-" + 6682a4a416Slntue cpp::to_string(FXRep::FRACTION_LEN); 6782a4a416Slntue } 6882a4a416Slntue #endif // LIBC_COMPILER_HAS_FIXED_POINT 6982a4a416Slntue 70fd2c74c8SGuillaume Chatelet cpp::string_view describeValue(const cpp::string &Value) { return Value; } 71f5dcab0dSGuillaume Chatelet cpp::string_view describeValue(cpp::string_view Value) { return Value; } 72af1315c2SSiva Chandra Reddy 73af1315c2SSiva Chandra Reddy template <typename ValType> 74fd2c74c8SGuillaume Chatelet bool test(RunContext *Ctx, TestCond Cond, ValType LHS, ValType RHS, 758e44b849SGuillaume Chatelet const char *LHSStr, const char *RHSStr, Location Loc) { 76fd2c74c8SGuillaume Chatelet auto ExplainDifference = [=, &Ctx](bool Cond, 77fd2c74c8SGuillaume Chatelet cpp::string_view OpString) -> bool { 78fd2c74c8SGuillaume Chatelet if (Cond) 79fd2c74c8SGuillaume Chatelet return true; 80fd2c74c8SGuillaume Chatelet Ctx->markFail(); 81af1315c2SSiva Chandra Reddy size_t OffsetLength = OpString.size() > 2 ? OpString.size() - 2 : 0; 82f5dcab0dSGuillaume Chatelet cpp::string Offset(OffsetLength, ' '); 838e44b849SGuillaume Chatelet tlog << Loc; 848e44b849SGuillaume Chatelet tlog << Offset << "Expected: " << LHSStr << '\n' 85af1315c2SSiva Chandra Reddy << Offset << "Which is: " << describeValue(LHS) << '\n' 86af1315c2SSiva Chandra Reddy << "To be " << OpString << ": " << RHSStr << '\n' 87af1315c2SSiva Chandra Reddy << Offset << "Which is: " << describeValue(RHS) << '\n'; 88fd2c74c8SGuillaume Chatelet return false; 89af1315c2SSiva Chandra Reddy }; 90af1315c2SSiva Chandra Reddy 91af1315c2SSiva Chandra Reddy switch (Cond) { 92fd2c74c8SGuillaume Chatelet case TestCond::EQ: 93fd2c74c8SGuillaume Chatelet return ExplainDifference(LHS == RHS, "equal to"); 94fd2c74c8SGuillaume Chatelet case TestCond::NE: 95fd2c74c8SGuillaume Chatelet return ExplainDifference(LHS != RHS, "not equal to"); 96fd2c74c8SGuillaume Chatelet case TestCond::LT: 97fd2c74c8SGuillaume Chatelet return ExplainDifference(LHS < RHS, "less than"); 98fd2c74c8SGuillaume Chatelet case TestCond::LE: 99fd2c74c8SGuillaume Chatelet return ExplainDifference(LHS <= RHS, "less than or equal to"); 100fd2c74c8SGuillaume Chatelet case TestCond::GT: 101fd2c74c8SGuillaume Chatelet return ExplainDifference(LHS > RHS, "greater than"); 102fd2c74c8SGuillaume Chatelet case TestCond::GE: 103fd2c74c8SGuillaume Chatelet return ExplainDifference(LHS >= RHS, "greater than or equal to"); 104af1315c2SSiva Chandra Reddy } 1058fc87f54SMikhail R. Gadelha __builtin_unreachable(); 106af1315c2SSiva Chandra Reddy } 107af1315c2SSiva Chandra Reddy 108af1315c2SSiva Chandra Reddy } // namespace internal 109af1315c2SSiva Chandra Reddy 110af1315c2SSiva Chandra Reddy Test *Test::Start = nullptr; 111af1315c2SSiva Chandra Reddy Test *Test::End = nullptr; 112af1315c2SSiva Chandra Reddy 1131e8960c7SSiva Chandra Reddy int argc = 0; 1141e8960c7SSiva Chandra Reddy char **argv = nullptr; 1151e8960c7SSiva Chandra Reddy char **envp = nullptr; 1161e8960c7SSiva Chandra Reddy 1171e8960c7SSiva Chandra Reddy using internal::RunContext; 1181e8960c7SSiva Chandra Reddy 119af1315c2SSiva Chandra Reddy void Test::addTest(Test *T) { 120af1315c2SSiva Chandra Reddy if (End == nullptr) { 121af1315c2SSiva Chandra Reddy Start = T; 122af1315c2SSiva Chandra Reddy End = T; 123af1315c2SSiva Chandra Reddy return; 124af1315c2SSiva Chandra Reddy } 125af1315c2SSiva Chandra Reddy 126af1315c2SSiva Chandra Reddy End->Next = T; 127af1315c2SSiva Chandra Reddy End = T; 128af1315c2SSiva Chandra Reddy } 129af1315c2SSiva Chandra Reddy 1306f576d95SNick Desaulniers (paternity leave) int Test::getNumTests() { 1316f576d95SNick Desaulniers (paternity leave) int N = 0; 1326f576d95SNick Desaulniers (paternity leave) for (Test *T = Start; T; T = T->Next, ++N) 1336f576d95SNick Desaulniers (paternity leave) ; 1346f576d95SNick Desaulniers (paternity leave) return N; 1356f576d95SNick Desaulniers (paternity leave) } 1366f576d95SNick Desaulniers (paternity leave) 1376f576d95SNick Desaulniers (paternity leave) int Test::runTests(const TestOptions &Options) { 1386f576d95SNick Desaulniers (paternity leave) const char *green = Options.PrintColor ? "\033[32m" : ""; 1396f576d95SNick Desaulniers (paternity leave) const char *red = Options.PrintColor ? "\033[31m" : ""; 1406f576d95SNick Desaulniers (paternity leave) const char *reset = Options.PrintColor ? "\033[0m" : ""; 1416f576d95SNick Desaulniers (paternity leave) 1426f576d95SNick Desaulniers (paternity leave) int TestCount = getNumTests(); 1436f576d95SNick Desaulniers (paternity leave) if (TestCount) { 1446f576d95SNick Desaulniers (paternity leave) tlog << green << "[==========] " << reset << "Running " << TestCount 1456f576d95SNick Desaulniers (paternity leave) << " test"; 1466f576d95SNick Desaulniers (paternity leave) if (TestCount > 1) 1476f576d95SNick Desaulniers (paternity leave) tlog << "s"; 1486f576d95SNick Desaulniers (paternity leave) tlog << " from 1 test suite.\n"; 1496f576d95SNick Desaulniers (paternity leave) } 1506f576d95SNick Desaulniers (paternity leave) 151af1315c2SSiva Chandra Reddy int FailCount = 0; 152af1315c2SSiva Chandra Reddy for (Test *T = Start; T != nullptr; T = T->Next) { 153af1315c2SSiva Chandra Reddy const char *TestName = T->getName(); 1546f576d95SNick Desaulniers (paternity leave) 1556f576d95SNick Desaulniers (paternity leave) if (Options.TestFilter && cpp::string(TestName) != Options.TestFilter) { 1566f576d95SNick Desaulniers (paternity leave) --TestCount; 157af1315c2SSiva Chandra Reddy continue; 158af1315c2SSiva Chandra Reddy } 1596f576d95SNick Desaulniers (paternity leave) 1606f576d95SNick Desaulniers (paternity leave) tlog << green << "[ RUN ] " << reset << TestName << '\n'; 161106621b6SMikhail R. Gadelha [[maybe_unused]] const uint64_t start_time = clock(); 162af1315c2SSiva Chandra Reddy RunContext Ctx; 163af1315c2SSiva Chandra Reddy T->SetUp(); 164af1315c2SSiva Chandra Reddy T->setContext(&Ctx); 165af1315c2SSiva Chandra Reddy T->Run(); 166af1315c2SSiva Chandra Reddy T->TearDown(); 167106621b6SMikhail R. Gadelha [[maybe_unused]] const uint64_t end_time = clock(); 168fd2c74c8SGuillaume Chatelet switch (Ctx.status()) { 169fd2c74c8SGuillaume Chatelet case RunContext::RunResult::Fail: 1706f576d95SNick Desaulniers (paternity leave) tlog << red << "[ FAILED ] " << reset << TestName << '\n'; 171af1315c2SSiva Chandra Reddy ++FailCount; 172af1315c2SSiva Chandra Reddy break; 173fd2c74c8SGuillaume Chatelet case RunContext::RunResult::Pass: 1746f576d95SNick Desaulniers (paternity leave) tlog << green << "[ OK ] " << reset << TestName; 175158d7b8cSJoseph Huber #ifdef LIBC_TEST_USE_CLOCK 1766f576d95SNick Desaulniers (paternity leave) tlog << " ("; 17704e066dfSGuillaume Chatelet if (start_time > end_time) { 17804e066dfSGuillaume Chatelet tlog << "unknown - try rerunning)\n"; 17904e066dfSGuillaume Chatelet } else { 18004e066dfSGuillaume Chatelet const auto duration = end_time - start_time; 1815db39796SJoseph Huber const uint64_t duration_ms = (duration * 1000) / CLOCKS_PER_SEC; 1825db39796SJoseph Huber const uint64_t duration_us = (duration * 1000 * 1000) / CLOCKS_PER_SEC; 1835db39796SJoseph Huber const uint64_t duration_ns = 1845db39796SJoseph Huber (duration * 1000 * 1000 * 1000) / CLOCKS_PER_SEC; 1856f576d95SNick Desaulniers (paternity leave) if (Options.TimeInMs || duration_ms != 0) 18604e066dfSGuillaume Chatelet tlog << duration_ms << " ms)\n"; 1875db39796SJoseph Huber else if (duration_us != 0) 1885db39796SJoseph Huber tlog << duration_us << " us)\n"; 1895db39796SJoseph Huber else 1905db39796SJoseph Huber tlog << duration_ns << " ns)\n"; 19104e066dfSGuillaume Chatelet } 19204e066dfSGuillaume Chatelet #else 19304e066dfSGuillaume Chatelet tlog << '\n'; 19404e066dfSGuillaume Chatelet #endif 195af1315c2SSiva Chandra Reddy break; 196af1315c2SSiva Chandra Reddy } 197af1315c2SSiva Chandra Reddy } 198af1315c2SSiva Chandra Reddy 199af1315c2SSiva Chandra Reddy if (TestCount > 0) { 200f5dcab0dSGuillaume Chatelet tlog << "Ran " << TestCount << " tests. " 201f5dcab0dSGuillaume Chatelet << " PASS: " << TestCount - FailCount << ' ' << " FAIL: " << FailCount 202f5dcab0dSGuillaume Chatelet << '\n'; 203af1315c2SSiva Chandra Reddy } else { 204f5dcab0dSGuillaume Chatelet tlog << "No tests run.\n"; 2056f576d95SNick Desaulniers (paternity leave) if (Options.TestFilter) { 2066f576d95SNick Desaulniers (paternity leave) tlog << "No matching test for " << Options.TestFilter << '\n'; 207af1315c2SSiva Chandra Reddy } 208af1315c2SSiva Chandra Reddy } 209af1315c2SSiva Chandra Reddy 210af1315c2SSiva Chandra Reddy return FailCount > 0 || TestCount == 0 ? 1 : 0; 211af1315c2SSiva Chandra Reddy } 212af1315c2SSiva Chandra Reddy 213af1315c2SSiva Chandra Reddy namespace internal { 214af1315c2SSiva Chandra Reddy 21582a4a416Slntue #define TEST_SPECIALIZATION(TYPE) \ 21682a4a416Slntue template bool test<TYPE>(RunContext * Ctx, TestCond Cond, TYPE LHS, \ 21782a4a416Slntue TYPE RHS, const char *LHSStr, const char *RHSStr, \ 21882a4a416Slntue Location Loc) 219af1315c2SSiva Chandra Reddy 22082a4a416Slntue TEST_SPECIALIZATION(char); 22182a4a416Slntue TEST_SPECIALIZATION(short); 22282a4a416Slntue TEST_SPECIALIZATION(int); 22382a4a416Slntue TEST_SPECIALIZATION(long); 22482a4a416Slntue TEST_SPECIALIZATION(long long); 225af1315c2SSiva Chandra Reddy 22682a4a416Slntue TEST_SPECIALIZATION(unsigned char); 22782a4a416Slntue TEST_SPECIALIZATION(unsigned short); 22882a4a416Slntue TEST_SPECIALIZATION(unsigned int); 22982a4a416Slntue TEST_SPECIALIZATION(unsigned long); 23082a4a416Slntue TEST_SPECIALIZATION(unsigned long long); 231fd2c74c8SGuillaume Chatelet 23282a4a416Slntue TEST_SPECIALIZATION(bool); 233af1315c2SSiva Chandra Reddy 234af1315c2SSiva Chandra Reddy // We cannot just use a single UInt128 specialization as that resolves to only 235af1315c2SSiva Chandra Reddy // one type, UInt<128> or __uint128_t. We want both overloads as we want to 23623c397c7SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT128 237af1315c2SSiva Chandra Reddy // When builtin __uint128_t type is available, include its specialization 238af1315c2SSiva Chandra Reddy // also. 23982a4a416Slntue TEST_SPECIALIZATION(__uint128_t); 24023c397c7SGuillaume Chatelet #endif // LIBC_TYPES_HAS_INT128 241af1315c2SSiva Chandra Reddy 2426a8e6c9aSGuillaume Chatelet TEST_SPECIALIZATION(LIBC_NAMESPACE::Int<128>); 2431557256aSTue Ly 244*7302c8dbSNick Desaulniers TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<96>); 2456a8e6c9aSGuillaume Chatelet TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<128>); 2466a8e6c9aSGuillaume Chatelet TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<192>); 2476a8e6c9aSGuillaume Chatelet TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<256>); 2486a8e6c9aSGuillaume Chatelet TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<320>); 249af1315c2SSiva Chandra Reddy 25082a4a416Slntue TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::string_view); 25182a4a416Slntue TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::string); 252af1315c2SSiva Chandra Reddy 25382a4a416Slntue #ifdef LIBC_COMPILER_HAS_FIXED_POINT 25482a4a416Slntue TEST_SPECIALIZATION(short fract); 25582a4a416Slntue TEST_SPECIALIZATION(fract); 25682a4a416Slntue TEST_SPECIALIZATION(long fract); 25782a4a416Slntue TEST_SPECIALIZATION(unsigned short fract); 25882a4a416Slntue TEST_SPECIALIZATION(unsigned fract); 25982a4a416Slntue TEST_SPECIALIZATION(unsigned long fract); 260af1315c2SSiva Chandra Reddy 26182a4a416Slntue TEST_SPECIALIZATION(short accum); 26282a4a416Slntue TEST_SPECIALIZATION(accum); 26382a4a416Slntue TEST_SPECIALIZATION(long accum); 26482a4a416Slntue TEST_SPECIALIZATION(unsigned short accum); 26582a4a416Slntue TEST_SPECIALIZATION(unsigned accum); 26682a4a416Slntue TEST_SPECIALIZATION(unsigned long accum); 26782a4a416Slntue #endif // LIBC_COMPILER_HAS_FIXED_POINT 268b6bc9d72SGuillaume Chatelet 269af1315c2SSiva Chandra Reddy } // namespace internal 270af1315c2SSiva Chandra Reddy 271af1315c2SSiva Chandra Reddy bool Test::testStrEq(const char *LHS, const char *RHS, const char *LHSStr, 2728e44b849SGuillaume Chatelet const char *RHSStr, internal::Location Loc) { 2738e44b849SGuillaume Chatelet return internal::test( 2748e44b849SGuillaume Chatelet Ctx, TestCond::EQ, LHS ? cpp::string_view(LHS) : cpp::string_view(), 2758e44b849SGuillaume Chatelet RHS ? cpp::string_view(RHS) : cpp::string_view(), LHSStr, RHSStr, Loc); 276af1315c2SSiva Chandra Reddy } 277af1315c2SSiva Chandra Reddy 278af1315c2SSiva Chandra Reddy bool Test::testStrNe(const char *LHS, const char *RHS, const char *LHSStr, 2798e44b849SGuillaume Chatelet const char *RHSStr, internal::Location Loc) { 2808e44b849SGuillaume Chatelet return internal::test( 2818e44b849SGuillaume Chatelet Ctx, TestCond::NE, LHS ? cpp::string_view(LHS) : cpp::string_view(), 2828e44b849SGuillaume Chatelet RHS ? cpp::string_view(RHS) : cpp::string_view(), LHSStr, RHSStr, Loc); 283af1315c2SSiva Chandra Reddy } 284af1315c2SSiva Chandra Reddy 285af1315c2SSiva Chandra Reddy bool Test::testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr, 2868e44b849SGuillaume Chatelet const char *RHSStr, internal::Location Loc) { 287af1315c2SSiva Chandra Reddy if (MatchResult) 288af1315c2SSiva Chandra Reddy return true; 289af1315c2SSiva Chandra Reddy 290af1315c2SSiva Chandra Reddy Ctx->markFail(); 291af1315c2SSiva Chandra Reddy if (!Matcher.is_silent()) { 2928e44b849SGuillaume Chatelet tlog << Loc; 2938e44b849SGuillaume Chatelet tlog << "Failed to match " << LHSStr << " against " << RHSStr << ".\n"; 294dcf296b5SSiva Chandra Reddy Matcher.explainError(); 295af1315c2SSiva Chandra Reddy } 296af1315c2SSiva Chandra Reddy return false; 297af1315c2SSiva Chandra Reddy } 298af1315c2SSiva Chandra Reddy 299af1315c2SSiva Chandra Reddy } // namespace testing 3005ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 301