xref: /llvm-project/libc/test/UnitTest/LibcTest.cpp (revision 7302c8dbe71b7c03b73a35a21fa4b415fa1f4505)
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