diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h --- a/libc/test/UnitTest/FPMatcher.h +++ b/libc/test/UnitTest/FPMatcher.h @@ -77,6 +77,11 @@ __llvm_libc::testing::getMatcher<__llvm_libc::testing::TestCond::EQ>( \ expected)) +#define TEST_FP_EQ(expected, actual) \ + __llvm_libc::testing::getMatcher<__llvm_libc::testing::TestCond::EQ>( \ + expected) \ + .match(actual) + #define EXPECT_FP_IS_NAN(actual) EXPECT_TRUE((actual) != (actual)) #define ASSERT_FP_EQ(expected, actual) \ diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h --- a/libc/test/UnitTest/LibcTest.h +++ b/libc/test/UnitTest/LibcTest.h @@ -42,17 +42,46 @@ // conditions for such cases. enum class TestCond { EQ, NE, LT, LE, GT, GE }; +struct MatcherBase { + virtual ~MatcherBase() {} + virtual void explainError() { tlog << "unknown error\n"; } + // Override and return true to skip `explainError` step. + virtual bool is_silent() const { return false; } +}; + +template struct Matcher : public MatcherBase { + bool match(const T &t); +}; + namespace internal { +// A simple location object to allow consistent passing of __FILE__ and +// __LINE__. struct Location { Location(const char *file, int line) : file(file), line(line) {} const char *file; int line; }; +// Supports writing a failing Location to tlog. TestLogger &operator<<(TestLogger &logger, Location Loc); -#define LOC() __llvm_libc::testing::internal::Location(__FILE__, __LINE__) +#define LIBC_TEST_LOC_() \ + __llvm_libc::testing::internal::Location(__FILE__, __LINE__) + +// Object to forward custom logging after the EXPECT / ASSERT macros. +struct Message { + template Message &operator<<(T value) { + tlog << value; + return *this; + } +}; + +// A trivial object to catch the Message, this enables custom logging and +// returning from the test function, see LIBC_TEST_SCAFFOLDING_ below. +struct Failure { + void operator=(Message msg) {} +}; struct RunContext { enum class RunResult : bool { Pass, Fail }; @@ -71,17 +100,6 @@ } // namespace internal -struct MatcherBase { - virtual ~MatcherBase() {} - virtual void explainError() { tlog << "unknown error\n"; } - // Override and return true to skip `explainError` step. - virtual bool is_silent() const { return false; } -}; - -template struct Matcher : public MatcherBase { - bool match(T &t); -}; - // NOTE: One should not create instances and call methods on them directly. One // should use the macros TEST or TEST_F to write test cases. class Test { @@ -156,6 +174,13 @@ bool testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr, const char *RHSStr, internal::Location Loc); + template + bool matchAndExplain(MatcherT &&Matcher, ValType Value, + const char *MatcherStr, const char *ValueStr, + internal::Location Loc) { + return testMatch(Matcher.match(Value), Matcher, ValueStr, MatcherStr, Loc); + } + bool testProcessExits(testutils::FunctionCaller *Func, int ExitCode, const char *LHSStr, const char *RHSStr, internal::Location Loc); @@ -351,106 +376,120 @@ SuiteClass##_##TestName SuiteClass##_##TestName##_Instance; \ void SuiteClass##_##TestName::Run() -#define EXPECT_EQ(LHS, RHS) \ - this->test(__llvm_libc::testing::TestCond::EQ, (LHS), (RHS), #LHS, #RHS, \ - LOC()) -#define ASSERT_EQ(LHS, RHS) \ - if (!EXPECT_EQ(LHS, RHS)) \ - return - -#define EXPECT_NE(LHS, RHS) \ - this->test(__llvm_libc::testing::TestCond::NE, (LHS), (RHS), #LHS, #RHS, \ - LOC()) -#define ASSERT_NE(LHS, RHS) \ - if (!EXPECT_NE(LHS, RHS)) \ - return - -#define EXPECT_LT(LHS, RHS) \ - this->test(__llvm_libc::testing::TestCond::LT, (LHS), (RHS), #LHS, #RHS, \ - LOC()) -#define ASSERT_LT(LHS, RHS) \ - if (!EXPECT_LT(LHS, RHS)) \ - return - -#define EXPECT_LE(LHS, RHS) \ - this->test(__llvm_libc::testing::TestCond::LE, (LHS), (RHS), #LHS, #RHS, \ - LOC()) -#define ASSERT_LE(LHS, RHS) \ - if (!EXPECT_LE(LHS, RHS)) \ - return - -#define EXPECT_GT(LHS, RHS) \ - this->test(__llvm_libc::testing::TestCond::GT, (LHS), (RHS), #LHS, #RHS, \ - LOC()) -#define ASSERT_GT(LHS, RHS) \ - if (!EXPECT_GT(LHS, RHS)) \ - return - -#define EXPECT_GE(LHS, RHS) \ - this->test(__llvm_libc::testing::TestCond::GE, (LHS), (RHS), #LHS, #RHS, \ - LOC()) -#define ASSERT_GE(LHS, RHS) \ - if (!EXPECT_GE(LHS, RHS)) \ - return - -#define EXPECT_STREQ(LHS, RHS) this->testStrEq((LHS), (RHS), #LHS, #RHS, LOC()) -#define ASSERT_STREQ(LHS, RHS) \ - if (!EXPECT_STREQ(LHS, RHS)) \ - return - -#define EXPECT_STRNE(LHS, RHS) this->testStrNe((LHS), (RHS), #LHS, #RHS, LOC()) -#define ASSERT_STRNE(LHS, RHS) \ - if (!EXPECT_STRNE(LHS, RHS)) \ - return - -#define EXPECT_TRUE(VAL) EXPECT_EQ((VAL), true) - -#define ASSERT_TRUE(VAL) \ - if (!EXPECT_TRUE(VAL)) \ - return - -#define EXPECT_FALSE(VAL) EXPECT_EQ((VAL), false) - -#define ASSERT_FALSE(VAL) \ - if (!EXPECT_FALSE(VAL)) \ - return +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#define LIBC_AMBIGUOUS_ELSE_BLOCKER_ \ + switch (0) \ + case 0: \ + default: + +// If RET_OR_EMPTY is the 'return' keyword we perform an early return which +// corresponds to an assert. If it is empty the execution continues, this +// corresponds to an expect. +// +// The 'else' clause must not be enclosed into braces so that the << operator +// can be used to fill the Message. +// +// TEST is usually implemented as a function performing checking logic and +// returning a boolean. This expression is responsible for logging the +// diagnostic in case of failure. +#define LIBC_TEST_SCAFFOLDING_(TEST, RET_OR_EMPTY) \ + LIBC_AMBIGUOUS_ELSE_BLOCKER_ \ + if (TEST) \ + ; \ + else \ + RET_OR_EMPTY __llvm_libc::testing::internal::Failure() = \ + __llvm_libc::testing::internal::Message() + +#define LIBC_TEST_BINOP_(COND, LHS, RHS, RET_OR_EMPTY) \ + LIBC_TEST_SCAFFOLDING_(test(__llvm_libc::testing::TestCond::COND, LHS, RHS, \ + #LHS, #RHS, LIBC_TEST_LOC_()), \ + RET_OR_EMPTY) + +//////////////////////////////////////////////////////////////////////////////// +// Binary operations corresponding to the TestCond enum. + +#define EXPECT_EQ(LHS, RHS) LIBC_TEST_BINOP_(EQ, LHS, RHS, ) +#define ASSERT_EQ(LHS, RHS) LIBC_TEST_BINOP_(EQ, LHS, RHS, return) + +#define EXPECT_NE(LHS, RHS) LIBC_TEST_BINOP_(NE, LHS, RHS, ) +#define ASSERT_NE(LHS, RHS) LIBC_TEST_BINOP_(NE, LHS, RHS, return) + +#define EXPECT_LT(LHS, RHS) LIBC_TEST_BINOP_(LT, LHS, RHS, ) +#define ASSERT_LT(LHS, RHS) LIBC_TEST_BINOP_(LT, LHS, RHS, return) + +#define EXPECT_LE(LHS, RHS) LIBC_TEST_BINOP_(LE, LHS, RHS, ) +#define ASSERT_LE(LHS, RHS) LIBC_TEST_BINOP_(LE, LHS, RHS, return) + +#define EXPECT_GT(LHS, RHS) LIBC_TEST_BINOP_(GT, LHS, RHS, ) +#define ASSERT_GT(LHS, RHS) LIBC_TEST_BINOP_(GT, LHS, RHS, return) + +#define EXPECT_GE(LHS, RHS) LIBC_TEST_BINOP_(GE, LHS, RHS, ) +#define ASSERT_GE(LHS, RHS) LIBC_TEST_BINOP_(GE, LHS, RHS, return) + +//////////////////////////////////////////////////////////////////////////////// +// Boolean checks are handled as comparison to the true / false values. + +#define EXPECT_TRUE(VAL) EXPECT_EQ(VAL, true) +#define ASSERT_TRUE(VAL) ASSERT_EQ(VAL, true) + +#define EXPECT_FALSE(VAL) EXPECT_EQ(VAL, false) +#define ASSERT_FALSE(VAL) ASSERT_EQ(VAL, false) + +//////////////////////////////////////////////////////////////////////////////// +// String checks. + +#define LIBC_TEST_STR_(TEST_FUNC, LHS, RHS, RET_OR_EMPTY) \ + LIBC_TEST_SCAFFOLDING_(TEST_FUNC(LHS, RHS, #LHS, #RHS, LIBC_TEST_LOC_()), \ + RET_OR_EMPTY) + +#define EXPECT_STREQ(LHS, RHS) LIBC_TEST_STR_(testStrEq, LHS, RHS, ) +#define ASSERT_STREQ(LHS, RHS) LIBC_TEST_STR_(testStrEq, LHS, RHS, return) + +#define EXPECT_STRNE(LHS, RHS) LIBC_TEST_STR_(testStrNe, LHS, RHS, ) +#define ASSERT_STRNE(LHS, RHS) LIBC_TEST_STR_(testStrNe, LHS, RHS, return) + +//////////////////////////////////////////////////////////////////////////////// +// Subprocess checks. #ifdef ENABLE_SUBPROCESS_TESTS -#define EXPECT_EXITS(FUNC, EXIT) \ - this->testProcessExits(__llvm_libc::testing::Test::createCallable(FUNC), \ - EXIT, #FUNC, #EXIT, LOC()) +#define LIBC_TEST_PROCESS_(TEST_FUNC, FUNC, VALUE, RET_OR_EMPTY) \ + LIBC_TEST_SCAFFOLDING_( \ + TEST_FUNC(__llvm_libc::testing::Test::createCallable(FUNC), VALUE, \ + #FUNC, #VALUE, LIBC_TEST_LOC_()), \ + RET_OR_EMPTY) +#define EXPECT_EXITS(FUNC, EXIT) \ + LIBC_TEST_PROCESS_(testProcessExits, FUNC, EXIT, ) #define ASSERT_EXITS(FUNC, EXIT) \ - if (!EXPECT_EXITS(FUNC, EXIT)) \ - return + LIBC_TEST_PROCESS_(testProcessExits, FUNC, EXIT, return) #define EXPECT_DEATH(FUNC, SIG) \ - this->testProcessKilled(__llvm_libc::testing::Test::createCallable(FUNC), \ - SIG, #FUNC, #SIG, LOC()) - -#define ASSERT_DEATH(FUNC, EXIT) \ - if (!EXPECT_DEATH(FUNC, EXIT)) \ - return + LIBC_TEST_PROCESS_(testProcessKilled, FUNC, SIG, ) +#define ASSERT_DEATH(FUNC, SIG) \ + LIBC_TEST_PROCESS_(testProcessKilled, FUNC, SIG, return) #endif // ENABLE_SUBPROCESS_TESTS -#define __CAT1(a, b) a##b -#define __CAT(a, b) __CAT1(a, b) -#define UNIQUE_VAR(prefix) __CAT(prefix, __LINE__) +//////////////////////////////////////////////////////////////////////////////// +// Custom matcher checks. -#define EXPECT_THAT(MATCH, MATCHER) \ - [&]() -> bool { \ - auto UNIQUE_VAR(__matcher) = (MATCHER); \ - return this->testMatch(UNIQUE_VAR(__matcher).match((MATCH)), \ - UNIQUE_VAR(__matcher), #MATCH, #MATCHER, LOC()); \ - }() +#define LIBC_TEST_MATCH_(MATCHER, MATCH, MATCHER_STR, MATCH_STR, RET_OR_EMPTY) \ + LIBC_TEST_SCAFFOLDING_(matchAndExplain(MATCHER, MATCH, MATCHER_STR, \ + MATCH_STR, LIBC_TEST_LOC_()), \ + RET_OR_EMPTY) +#define EXPECT_THAT(MATCH, MATCHER) \ + LIBC_TEST_MATCH_(MATCHER, MATCH, #MATCHER, #MATCH, ) #define ASSERT_THAT(MATCH, MATCHER) \ - do { \ - if (!EXPECT_THAT(MATCH, MATCHER)) \ - return; \ - } while (0) + LIBC_TEST_MATCH_(MATCHER, MATCH, #MATCHER, #MATCH, return) #define WITH_SIGNAL(X) X diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp --- a/libc/test/UnitTest/LibcTest.cpp +++ b/libc/test/UnitTest/LibcTest.cpp @@ -29,7 +29,8 @@ return logger << Loc.file << ":" << Loc.line << ": FAILURE\n"; } -// When the value is UInt128, __uint128_t or wider, show its hexadecimal digits. +// When the value is UInt128, __uint128_t or wider, show its hexadecimal +// digits. template cpp::enable_if_t && (sizeof(T) > sizeof(uint64_t)), cpp::string> diff --git a/libc/test/UnitTest/TestLogger.cpp b/libc/test/UnitTest/TestLogger.cpp --- a/libc/test/UnitTest/TestLogger.cpp +++ b/libc/test/UnitTest/TestLogger.cpp @@ -2,6 +2,7 @@ #include "src/__support/CPP/string.h" #include "src/__support/CPP/string_view.h" #include "src/__support/OSUtil/io.h" // write_to_stderr +#include "src/__support/UInt128.h" #include @@ -35,24 +36,49 @@ return *this << cpp::string_view(&ch, 1); } +// bool specialization +template <> TestLogger &TestLogger::operator<<(bool cond) { + return *this << (cond ? "true" : "false"); +} + // void * specialization template <> TestLogger &TestLogger::operator<<(void *addr) { return *this << "0x" << cpp::to_string(reinterpret_cast(addr)); } template TestLogger &TestLogger::operator<<(T t) { - return *this << cpp::to_string(t); + if constexpr (cpp::is_integral_v && cpp::is_unsigned_v && + sizeof(T) > sizeof(uint64_t)) { + static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); + char buf[IntegerToString::hex_bufsize()]; + IntegerToString::hex(t, buf, false); + return *this << "0x" << cpp::string_view(buf, sizeof(buf)); + } else { + return *this << cpp::to_string(t); + } } // is_integral specializations +// char is already specialized to handle character +template TestLogger &TestLogger::operator<< (short); template TestLogger &TestLogger::operator<< (int); -template TestLogger &TestLogger::operator<< (unsigned int); template TestLogger &TestLogger::operator<< (long); -template TestLogger &TestLogger::operator<< (unsigned long); template TestLogger &TestLogger::operator<< (long long); +template TestLogger &TestLogger::operator<< (unsigned char); +template TestLogger &TestLogger::operator<< (unsigned short); +template TestLogger &TestLogger::operator<< (unsigned int); +template TestLogger &TestLogger::operator<< (unsigned long); template TestLogger & TestLogger::operator<< (unsigned long long); +#ifdef __SIZEOF_INT128__ +template TestLogger &TestLogger::operator<< <__uint128_t>(__uint128_t); +#endif +template TestLogger &TestLogger::operator<< >(cpp::UInt<128>); +template TestLogger &TestLogger::operator<< >(cpp::UInt<192>); +template TestLogger &TestLogger::operator<< >(cpp::UInt<256>); +template TestLogger &TestLogger::operator<< >(cpp::UInt<320>); + // TODO: Add floating point formatting once it's supported by StringStream. TestLogger tlog; diff --git a/libc/test/src/math/exhaustive/acosf_test.cpp b/libc/test/src/math/exhaustive/acosf_test.cpp --- a/libc/test/src/math/exhaustive/acosf_test.cpp +++ b/libc/test/src/math/exhaustive/acosf_test.cpp @@ -26,8 +26,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Acos, x, - __llvm_libc::acosf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Acos, x, __llvm_libc::acosf(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/acoshf_test.cpp b/libc/test/src/math/exhaustive/acoshf_test.cpp --- a/libc/test/src/math/exhaustive/acoshf_test.cpp +++ b/libc/test/src/math/exhaustive/acoshf_test.cpp @@ -26,8 +26,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Acosh, x, - __llvm_libc::acoshf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Acosh, x, + __llvm_libc::acoshf(x), 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/asinf_test.cpp b/libc/test/src/math/exhaustive/asinf_test.cpp --- a/libc/test/src/math/exhaustive/asinf_test.cpp +++ b/libc/test/src/math/exhaustive/asinf_test.cpp @@ -26,8 +26,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Asin, x, - __llvm_libc::asinf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Asin, x, __llvm_libc::asinf(x), + 0.5, rounding); // if (!result) break; } while (bits++ < stop); return result; diff --git a/libc/test/src/math/exhaustive/asinhf_test.cpp b/libc/test/src/math/exhaustive/asinhf_test.cpp --- a/libc/test/src/math/exhaustive/asinhf_test.cpp +++ b/libc/test/src/math/exhaustive/asinhf_test.cpp @@ -26,8 +26,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Asinh, x, - __llvm_libc::asinhf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Asinh, x, + __llvm_libc::asinhf(x), 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/atanf_test.cpp b/libc/test/src/math/exhaustive/atanf_test.cpp --- a/libc/test/src/math/exhaustive/atanf_test.cpp +++ b/libc/test/src/math/exhaustive/atanf_test.cpp @@ -26,8 +26,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Atan, x, - __llvm_libc::atanf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Atan, x, __llvm_libc::atanf(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/atanhf_test.cpp b/libc/test/src/math/exhaustive/atanhf_test.cpp --- a/libc/test/src/math/exhaustive/atanhf_test.cpp +++ b/libc/test/src/math/exhaustive/atanhf_test.cpp @@ -26,8 +26,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Atanh, x, - __llvm_libc::atanhf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Atanh, x, + __llvm_libc::atanhf(x), 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/cosf_test.cpp b/libc/test/src/math/exhaustive/cosf_test.cpp --- a/libc/test/src/math/exhaustive/cosf_test.cpp +++ b/libc/test/src/math/exhaustive/cosf_test.cpp @@ -27,8 +27,8 @@ do { FPBits xbits(bits); float x = float(xbits); - bool r = EXPECT_MPFR_MATCH(mpfr::Operation::Cos, x, __llvm_libc::cosf(x), - 0.5, rounding); + bool r = TEST_MPFR_MATCH(mpfr::Operation::Cos, x, __llvm_libc::cosf(x), + 0.5, rounding); result &= r; } while (++bits < stop); return result; diff --git a/libc/test/src/math/exhaustive/coshf_test.cpp b/libc/test/src/math/exhaustive/coshf_test.cpp --- a/libc/test/src/math/exhaustive/coshf_test.cpp +++ b/libc/test/src/math/exhaustive/coshf_test.cpp @@ -27,8 +27,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Cosh, x, - __llvm_libc::coshf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Cosh, x, __llvm_libc::coshf(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/exp10f_test.cpp b/libc/test/src/math/exhaustive/exp10f_test.cpp --- a/libc/test/src/math/exhaustive/exp10f_test.cpp +++ b/libc/test/src/math/exhaustive/exp10f_test.cpp @@ -27,8 +27,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Exp10, x, - __llvm_libc::exp10f(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Exp10, x, + __llvm_libc::exp10f(x), 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/exp2f_test.cpp b/libc/test/src/math/exhaustive/exp2f_test.cpp --- a/libc/test/src/math/exhaustive/exp2f_test.cpp +++ b/libc/test/src/math/exhaustive/exp2f_test.cpp @@ -25,8 +25,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, - __llvm_libc::exp2f(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/expf_test.cpp b/libc/test/src/math/exhaustive/expf_test.cpp --- a/libc/test/src/math/exhaustive/expf_test.cpp +++ b/libc/test/src/math/exhaustive/expf_test.cpp @@ -27,8 +27,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), - 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/expm1f_test.cpp b/libc/test/src/math/exhaustive/expm1f_test.cpp --- a/libc/test/src/math/exhaustive/expm1f_test.cpp +++ b/libc/test/src/math/exhaustive/expm1f_test.cpp @@ -27,8 +27,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Expm1, x, - __llvm_libc::expm1f(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Expm1, x, + __llvm_libc::expm1f(x), 0.5, rounding); } while (bits-- > start); return result; } diff --git a/libc/test/src/math/exhaustive/hypotf_test.cpp b/libc/test/src/math/exhaustive/hypotf_test.cpp --- a/libc/test/src/math/exhaustive/hypotf_test.cpp +++ b/libc/test/src/math/exhaustive/hypotf_test.cpp @@ -32,8 +32,8 @@ uint32_t ybits = Y_START; do { float y = float(FPBits(ybits)); - result &= EXPECT_FP_EQ(__llvm_libc::fputil::hypot(x, y), - __llvm_libc::hypotf(x, y)); + result &= TEST_FP_EQ(__llvm_libc::fputil::hypot(x, y), + __llvm_libc::hypotf(x, y)); // Using MPFR will be much slower. // mpfr::BinaryInput input{x, y}; // EXPECT_MPFR_MATCH(mpfr::Operation::Hypot, input, diff --git a/libc/test/src/math/exhaustive/log10f_test.cpp b/libc/test/src/math/exhaustive/log10f_test.cpp --- a/libc/test/src/math/exhaustive/log10f_test.cpp +++ b/libc/test/src/math/exhaustive/log10f_test.cpp @@ -25,8 +25,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Log10, x, - __llvm_libc::log10f(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Log10, x, + __llvm_libc::log10f(x), 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/log1pf_test.cpp b/libc/test/src/math/exhaustive/log1pf_test.cpp --- a/libc/test/src/math/exhaustive/log1pf_test.cpp +++ b/libc/test/src/math/exhaustive/log1pf_test.cpp @@ -25,8 +25,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Log1p, x, - __llvm_libc::log1pf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Log1p, x, + __llvm_libc::log1pf(x), 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/log2f_test.cpp b/libc/test/src/math/exhaustive/log2f_test.cpp --- a/libc/test/src/math/exhaustive/log2f_test.cpp +++ b/libc/test/src/math/exhaustive/log2f_test.cpp @@ -25,8 +25,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Log2, x, - __llvm_libc::log2f(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Log2, x, __llvm_libc::log2f(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/logf_test.cpp b/libc/test/src/math/exhaustive/logf_test.cpp --- a/libc/test/src/math/exhaustive/logf_test.cpp +++ b/libc/test/src/math/exhaustive/logf_test.cpp @@ -25,8 +25,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Log, x, __llvm_libc::logf(x), - 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Log, x, __llvm_libc::logf(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/sincosf_test.cpp b/libc/test/src/math/exhaustive/sincosf_test.cpp --- a/libc/test/src/math/exhaustive/sincosf_test.cpp +++ b/libc/test/src/math/exhaustive/sincosf_test.cpp @@ -29,8 +29,8 @@ float x = float(xbits); float sinx, cosx; __llvm_libc::sincosf(x, &sinx, &cosx); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Sin, x, sinx, 0.5, rounding); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Cos, x, cosx, 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Sin, x, sinx, 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Cos, x, cosx, 0.5, rounding); } while (++bits < stop); return result; } diff --git a/libc/test/src/math/exhaustive/sinf_test.cpp b/libc/test/src/math/exhaustive/sinf_test.cpp --- a/libc/test/src/math/exhaustive/sinf_test.cpp +++ b/libc/test/src/math/exhaustive/sinf_test.cpp @@ -27,8 +27,8 @@ do { FPBits xbits(bits); float x = float(xbits); - bool r = EXPECT_MPFR_MATCH(mpfr::Operation::Sin, x, __llvm_libc::sinf(x), - 0.5, rounding); + bool r = TEST_MPFR_MATCH(mpfr::Operation::Sin, x, __llvm_libc::sinf(x), + 0.5, rounding); result &= r; } while (++bits < stop); return result; diff --git a/libc/test/src/math/exhaustive/sinhf_test.cpp b/libc/test/src/math/exhaustive/sinhf_test.cpp --- a/libc/test/src/math/exhaustive/sinhf_test.cpp +++ b/libc/test/src/math/exhaustive/sinhf_test.cpp @@ -27,8 +27,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Sinh, x, - __llvm_libc::sinhf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Sinh, x, __llvm_libc::sinhf(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/exhaustive/tanf_test.cpp b/libc/test/src/math/exhaustive/tanf_test.cpp --- a/libc/test/src/math/exhaustive/tanf_test.cpp +++ b/libc/test/src/math/exhaustive/tanf_test.cpp @@ -31,8 +31,8 @@ do { FPBits xbits(bits); float x = float(xbits); - bool r = EXPECT_MPFR_MATCH(mpfr::Operation::Tan, x, __llvm_libc::tanf(x), - 0.5, rounding); + bool r = TEST_MPFR_MATCH(mpfr::Operation::Tan, x, __llvm_libc::tanf(x), + 0.5, rounding); result &= r; if (!r) --tol; diff --git a/libc/test/src/math/exhaustive/tanhf_test.cpp b/libc/test/src/math/exhaustive/tanhf_test.cpp --- a/libc/test/src/math/exhaustive/tanhf_test.cpp +++ b/libc/test/src/math/exhaustive/tanhf_test.cpp @@ -26,8 +26,8 @@ do { FPBits xbits(bits); float x = float(xbits); - result &= EXPECT_MPFR_MATCH(mpfr::Operation::Tanh, x, - __llvm_libc::tanhf(x), 0.5, rounding); + result &= TEST_MPFR_MATCH(mpfr::Operation::Tanh, x, __llvm_libc::tanhf(x), + 0.5, rounding); } while (bits++ < stop); return result; } diff --git a/libc/test/src/math/log10_test.cpp b/libc/test/src/math/log10_test.cpp --- a/libc/test/src/math/log10_test.cpp +++ b/libc/test/src/math/log10_test.cpp @@ -105,11 +105,11 @@ ++count; // ASSERT_MPFR_MATCH(mpfr::Operation::Log10, x, result, 0.5); - if (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log10, x, - result, 0.5, rounding_mode)) { + if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log10, x, result, + 0.5, rounding_mode)) { ++fails; - while (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY( - mpfr::Operation::Log10, x, result, tol, rounding_mode)) { + while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log10, x, + result, tol, rounding_mode)) { mx = x; mr = result; tol *= 2.0; diff --git a/libc/test/src/math/log1p_test.cpp b/libc/test/src/math/log1p_test.cpp --- a/libc/test/src/math/log1p_test.cpp +++ b/libc/test/src/math/log1p_test.cpp @@ -106,11 +106,11 @@ ++count; // ASSERT_MPFR_MATCH(mpfr::Operation::Log1p, x, result, 0.5); - if (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log1p, x, - result, 0.5, rounding_mode)) { + if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log1p, x, result, + 0.5, rounding_mode)) { ++fails; - while (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY( - mpfr::Operation::Log1p, x, result, tol, rounding_mode)) { + while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log1p, x, + result, tol, rounding_mode)) { mx = x; mr = result; tol *= 2.0; diff --git a/libc/test/src/math/log2_test.cpp b/libc/test/src/math/log2_test.cpp --- a/libc/test/src/math/log2_test.cpp +++ b/libc/test/src/math/log2_test.cpp @@ -105,11 +105,11 @@ ++count; // ASSERT_MPFR_MATCH(mpfr::Operation::Log2, x, result, 0.5); - if (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log2, x, result, - 0.5, rounding_mode)) { + if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log2, x, result, + 0.5, rounding_mode)) { ++fails; - while (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY( - mpfr::Operation::Log2, x, result, tol, rounding_mode)) { + while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log2, x, + result, tol, rounding_mode)) { mx = x; mr = result; tol *= 2.0; diff --git a/libc/test/src/math/log_test.cpp b/libc/test/src/math/log_test.cpp --- a/libc/test/src/math/log_test.cpp +++ b/libc/test/src/math/log_test.cpp @@ -105,11 +105,11 @@ ++count; // ASSERT_MPFR_MATCH(mpfr::Operation::Log, x, result, 0.5); - if (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log, x, result, - 0.5, rounding_mode)) { + if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log, x, result, + 0.5, rounding_mode)) { ++fails; - while (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY( - mpfr::Operation::Log, x, result, tol, rounding_mode)) { + while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log, x, + result, tol, rounding_mode)) { mx = x; mr = result; tol *= 2.0; diff --git a/libc/test/src/string/bcopy_test.cpp b/libc/test/src/string/bcopy_test.cpp --- a/libc/test/src/string/bcopy_test.cpp +++ b/libc/test/src/string/bcopy_test.cpp @@ -23,7 +23,7 @@ const char Expected[] = {'a', 'b', 'y', 'z'}; void *const Dst = Buffer; __llvm_libc::bcopy(Buffer + 2, Dst, 0); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcBcopyTest, DstAndSrcPointToSameAddress) { @@ -31,7 +31,7 @@ const char Expected[] = {'a', 'b'}; void *const Dst = Buffer; __llvm_libc::bcopy(Buffer, Dst, 1); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcBcopyTest, DstStartsBeforeSrc) { @@ -41,7 +41,7 @@ const char Expected[] = {'z', 'b', 'c', 'c', 'z'}; void *const Dst = Buffer + 1; __llvm_libc::bcopy(Buffer + 2, Dst, 2); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcBcopyTest, DstStartsAfterSrc) { @@ -49,7 +49,7 @@ const char Expected[] = {'z', 'a', 'a', 'b', 'z'}; void *const Dst = Buffer + 2; __llvm_libc::bcopy(Buffer + 1, Dst, 2); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } // e.g. `Dst` follow `src`. @@ -61,7 +61,7 @@ const char Expected[] = {'z', 'b', 'b', 'z'}; void *const Dst = Buffer + 1; __llvm_libc::bcopy(Buffer + 2, Dst, 1); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcBcopyTest, DstFollowSrc) { @@ -69,7 +69,7 @@ const char Expected[] = {'z', 'a', 'a', 'z'}; void *const Dst = Buffer + 2; __llvm_libc::bcopy(Buffer + 1, Dst, 1); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } // Adapt CheckMemmove signature to bcopy. diff --git a/libc/test/src/string/memmem_test.cpp b/libc/test/src/string/memmem_test.cpp --- a/libc/test/src/string/memmem_test.cpp +++ b/libc/test/src/string/memmem_test.cpp @@ -31,21 +31,21 @@ char h[] = {'a', 'b', 'c'}; char *n = nullptr; void *result = __llvm_libc::memmem(h, sizeof(h), n, 0); - ASSERT_EQ(static_cast(result), h); + ASSERT_EQ(static_cast(result), h + 0); } TEST(LlvmLibcMemmemTest, ExactMatchReturnsHaystack) { char h[] = {'a', 'b', 'c'}; char n[] = {'a', 'b', 'c'}; void *result = __llvm_libc::memmem(h, sizeof(h), n, sizeof(n)); - ASSERT_EQ(static_cast(result), h); + ASSERT_EQ(static_cast(result), h + 0); } TEST(LlvmLibcMemmemTest, ReturnFirstMatchOfNeedle) { char h[] = {'a', 'a', 'b', 'c'}; char n[] = {'a'}; void *result = __llvm_libc::memmem(h, sizeof(h), n, sizeof(n)); - ASSERT_EQ(static_cast(result), h); + ASSERT_EQ(static_cast(result), h + 0); } TEST(LlvmLibcMemmemTest, ReturnFirstExactMatchOfNeedle) { @@ -102,7 +102,7 @@ char h[] = {'a', 'b', 'c'}; char n[] = {'x', 'y', 'z'}; void *result = __llvm_libc::memmem(h, sizeof(h), n, 0); - ASSERT_EQ(static_cast(result), h); + ASSERT_EQ(static_cast(result), h + 0); } { char h[] = {'a', 'b', 'c'}; diff --git a/libc/test/src/string/memmove_test.cpp b/libc/test/src/string/memmove_test.cpp --- a/libc/test/src/string/memmove_test.cpp +++ b/libc/test/src/string/memmove_test.cpp @@ -24,7 +24,7 @@ void *const Dst = Buffer; void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 0); EXPECT_EQ(Ret, Dst); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcMemmoveTest, DstAndSrcPointToSameAddress) { @@ -33,7 +33,7 @@ void *const Dst = Buffer; void *const Ret = __llvm_libc::memmove(Dst, Buffer, 1); EXPECT_EQ(Ret, Dst); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcMemmoveTest, DstStartsBeforeSrc) { @@ -44,7 +44,7 @@ void *const Dst = Buffer + 1; void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 2); EXPECT_EQ(Ret, Dst); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcMemmoveTest, DstStartsAfterSrc) { @@ -53,7 +53,7 @@ void *const Dst = Buffer + 2; void *const Ret = __llvm_libc::memmove(Dst, Buffer + 1, 2); EXPECT_EQ(Ret, Dst); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } // e.g. `Dst` follow `src`. @@ -66,7 +66,7 @@ void *const Dst = Buffer + 1; void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 1); EXPECT_EQ(Ret, Dst); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } TEST(LlvmLibcMemmoveTest, DstFollowSrc) { @@ -75,7 +75,7 @@ void *const Dst = Buffer + 2; void *const Ret = __llvm_libc::memmove(Dst, Buffer + 1, 1); EXPECT_EQ(Ret, Dst); - ASSERT_MEM_EQ(Buffer, Expected); + ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); } // Adapt CheckMemmove signature to op implementation signatures. diff --git a/libc/test/src/string/mempcpy_test.cpp b/libc/test/src/string/mempcpy_test.cpp --- a/libc/test/src/string/mempcpy_test.cpp +++ b/libc/test/src/string/mempcpy_test.cpp @@ -24,5 +24,5 @@ const char *src = "12345"; char dest[10]; void *result = __llvm_libc::mempcpy(dest, src, 0); - ASSERT_EQ(static_cast(result), dest); + ASSERT_EQ(static_cast(result), dest + 0); } diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h --- a/libc/utils/MPFRWrapper/MPFRUtils.h +++ b/libc/utils/MPFRWrapper/MPFRUtils.h @@ -339,6 +339,17 @@ EXPECT_MPFR_MATCH_DEFAULT, GET_MPFR_DUMMY_ARG) \ (__VA_ARGS__) +#define TEST_MPFR_MATCH_ROUNDING(op, input, match_value, ulp_tolerance, \ + rounding) \ + __llvm_libc::testing::mpfr::get_mpfr_matcher(input, match_value, \ + ulp_tolerance, rounding) \ + .match(match_value) + +#define TEST_MPFR_MATCH(...) \ + GET_MPFR_MACRO(__VA_ARGS__, TEST_MPFR_MATCH_ROUNDING, \ + EXPECT_MPFR_MATCH_DEFAULT, GET_MPFR_DUMMY_ARG) \ + (__VA_ARGS__) + #define EXPECT_MPFR_MATCH_ALL_ROUNDING(op, input, match_value, ulp_tolerance) \ { \ namespace mpfr = __llvm_libc::testing::mpfr; \ @@ -356,11 +367,11 @@ mpfr::RoundingMode::TowardZero); \ } -#define EXPECT_MPFR_MATCH_ROUNDING_SILENTLY(op, input, match_value, \ - ulp_tolerance, rounding) \ - EXPECT_THAT(match_value, \ - __llvm_libc::testing::mpfr::get_silent_mpfr_matcher( \ - input, match_value, ulp_tolerance, rounding)) +#define TEST_MPFR_MATCH_ROUNDING_SILENTLY(op, input, match_value, \ + ulp_tolerance, rounding) \ + __llvm_libc::testing::mpfr::get_silent_mpfr_matcher( \ + input, match_value, ulp_tolerance, rounding) \ + .match(match_value) #define ASSERT_MPFR_MATCH_DEFAULT(op, input, match_value, ulp_tolerance) \ ASSERT_THAT(match_value, \ diff --git a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel @@ -16,6 +16,7 @@ "//libc:__support_cpp_string", "//libc:__support_cpp_string_view", "//libc:__support_osutil_io", + "//libc:__support_uint128", "//libc:libc_root", ], )