diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h --- a/libc/src/__support/CPP/type_traits.h +++ b/libc/src/__support/CPP/type_traits.h @@ -85,6 +85,7 @@ template struct is_enum { static constexpr bool value = __is_enum(T); }; +template inline constexpr bool is_enum_v = is_enum::value; template struct is_pointer : cpp::false_type {}; template struct is_pointer : cpp::true_type {}; diff --git a/libc/test/UnitTest/LibcDeathTestExecutors.cpp b/libc/test/UnitTest/LibcDeathTestExecutors.cpp --- a/libc/test/UnitTest/LibcDeathTestExecutors.cpp +++ b/libc/test/UnitTest/LibcDeathTestExecutors.cpp @@ -18,26 +18,27 @@ bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line) { + internal::Location Loc) { testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500); if (const char *error = Result.get_error()) { Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" << error << '\n'; + tlog << Loc; + tlog << error << '\n'; return false; } if (Result.timed_out()) { Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" - << "Process timed out after " << 500 << " milliseconds.\n"; + tlog << Loc; + tlog << "Process timed out after " << 500 << " milliseconds.\n"; return false; } if (Result.exited_normally()) { Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" - << "Expected " << LHSStr + tlog << Loc; + tlog << "Expected " << LHSStr << " to be killed by a signal\nBut it exited normally!\n"; return false; } @@ -49,8 +50,8 @@ using testutils::signal_as_string; Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" - << " Expected: " << LHSStr << '\n' + tlog << Loc; + tlog << " Expected: " << LHSStr << '\n' << "To be killed by signal: " << Signal << '\n' << " Which is: " << signal_as_string(Signal) << '\n' << " But it was killed by: " << KilledBy << '\n' @@ -60,26 +61,27 @@ bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line) { + internal::Location Loc) { testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500); if (const char *error = Result.get_error()) { Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" << error << '\n'; + tlog << Loc; + tlog << error << '\n'; return false; } if (Result.timed_out()) { Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" - << "Process timed out after " << 500 << " milliseconds.\n"; + tlog << Loc; + tlog << "Process timed out after " << 500 << " milliseconds.\n"; return false; } if (!Result.exited_normally()) { Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" - << "Expected " << LHSStr << '\n' + tlog << Loc; + tlog << "Expected " << LHSStr << '\n' << "to exit with exit code " << ExitCode << '\n' << "But it exited abnormally!\n"; return false; @@ -90,8 +92,8 @@ return true; Ctx->markFail(); - tlog << File << ":" << Line << ": FAILURE\n" - << "Expected exit code of: " << LHSStr << '\n' + tlog << Loc; + tlog << "Expected exit code of: " << LHSStr << '\n' << " Which is: " << ActualExit << '\n' << " To be equal to: " << RHSStr << '\n' << " Which is: " << ExitCode << '\n'; 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 @@ -44,6 +44,16 @@ namespace internal { +struct Location { + Location(const char *file, int line) : file(file), line(line) {} + const char *file; + int line; +}; + +TestLogger &operator<<(TestLogger &logger, Location Loc); + +#define LOC() __llvm_libc::testing::internal::Location(__FILE__, __LINE__) + struct RunContext { enum class RunResult : bool { Pass, Fail }; @@ -57,8 +67,7 @@ template bool test(RunContext *Ctx, TestCond Cond, ValType LHS, ValType RHS, - const char *LHSStr, const char *RHSStr, const char *File, - unsigned long Line); + const char *LHSStr, const char *RHSStr, Location Loc); } // namespace internal @@ -76,7 +85,6 @@ // 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 { -private: Test *Next = nullptr; internal::RunContext *Ctx = nullptr; @@ -102,24 +110,24 @@ template , int> = 0> bool test(TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { - return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, File, Line); + const char *RHSStr, internal::Location Loc) { + return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, Loc); } template ::value, int> = 0> + cpp::enable_if_t, int> = 0> bool test(TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { + const char *RHSStr, internal::Location Loc) { return internal::test(Ctx, Cond, (long long)LHS, (long long)RHS, LHSStr, - RHSStr, File, Line); + RHSStr, Loc); } template , ValType> = nullptr> bool test(TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { + const char *RHSStr, internal::Location Loc) { return internal::test(Ctx, Cond, (unsigned long long)LHS, - (unsigned long long)RHS, LHSStr, RHSStr, File, Line); + (unsigned long long)RHS, LHSStr, RHSStr, Loc); } template < @@ -127,34 +135,34 @@ cpp::enable_if_t, int> = 0> bool test(TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { - return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, File, Line); + const char *RHSStr, internal::Location Loc) { + return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, Loc); } template , int> = 0> bool test(TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { - return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, File, Line); + const char *RHSStr, internal::Location Loc) { + return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, Loc); } bool testStrEq(const char *LHS, const char *RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line); + const char *RHSStr, internal::Location Loc); bool testStrNe(const char *LHS, const char *RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line); + const char *RHSStr, internal::Location Loc); bool testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line); + const char *RHSStr, internal::Location Loc); bool testProcessExits(testutils::FunctionCaller *Func, int ExitCode, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + internal::Location Loc); bool testProcessKilled(testutils::FunctionCaller *Func, int Signal, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + internal::Location Loc); template testutils::FunctionCaller *createCallable(Func f) { struct Callable : public testutils::FunctionCaller { @@ -345,54 +353,52 @@ #define EXPECT_EQ(LHS, RHS) \ this->test(__llvm_libc::testing::TestCond::EQ, (LHS), (RHS), #LHS, #RHS, \ - __FILE__, __LINE__) + 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, \ - __FILE__, __LINE__) + 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, \ - __FILE__, __LINE__) + 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, \ - __FILE__, __LINE__) + 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, \ - __FILE__, __LINE__) + 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, \ - __FILE__, __LINE__) + LOC()) #define ASSERT_GE(LHS, RHS) \ if (!EXPECT_GE(LHS, RHS)) \ return -#define EXPECT_STREQ(LHS, RHS) \ - this->testStrEq((LHS), (RHS), #LHS, #RHS, __FILE__, __LINE__) +#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, __FILE__, __LINE__) +#define EXPECT_STRNE(LHS, RHS) this->testStrNe((LHS), (RHS), #LHS, #RHS, LOC()) #define ASSERT_STRNE(LHS, RHS) \ if (!EXPECT_STRNE(LHS, RHS)) \ return @@ -413,7 +419,7 @@ #define EXPECT_EXITS(FUNC, EXIT) \ this->testProcessExits(__llvm_libc::testing::Test::createCallable(FUNC), \ - EXIT, #FUNC, #EXIT, __FILE__, __LINE__) + EXIT, #FUNC, #EXIT, LOC()) #define ASSERT_EXITS(FUNC, EXIT) \ if (!EXPECT_EXITS(FUNC, EXIT)) \ @@ -421,7 +427,7 @@ #define EXPECT_DEATH(FUNC, SIG) \ this->testProcessKilled(__llvm_libc::testing::Test::createCallable(FUNC), \ - SIG, #FUNC, #SIG, __FILE__, __LINE__) + SIG, #FUNC, #SIG, LOC()) #define ASSERT_DEATH(FUNC, EXIT) \ if (!EXPECT_DEATH(FUNC, EXIT)) \ @@ -437,8 +443,7 @@ [&]() -> bool { \ auto UNIQUE_VAR(__matcher) = (MATCHER); \ return this->testMatch(UNIQUE_VAR(__matcher).match((MATCH)), \ - UNIQUE_VAR(__matcher), #MATCH, #MATCHER, __FILE__, \ - __LINE__); \ + UNIQUE_VAR(__matcher), #MATCH, #MATCHER, LOC()); \ }() #define ASSERT_THAT(MATCH, MATCHER) \ 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 @@ -25,6 +25,10 @@ namespace internal { +TestLogger &operator<<(TestLogger &logger, Location Loc) { + return logger << Loc.file << ":" << Loc.line << ": FAILURE\n"; +} + // When the value is UInt128, __uint128_t or wider, show its hexadecimal digits. template cpp::enable_if_t && cpp::is_unsigned_v && @@ -51,8 +55,7 @@ template bool test(RunContext *Ctx, TestCond Cond, ValType LHS, ValType RHS, - const char *LHSStr, const char *RHSStr, const char *File, - unsigned long Line) { + const char *LHSStr, const char *RHSStr, Location Loc) { auto ExplainDifference = [=, &Ctx](bool Cond, cpp::string_view OpString) -> bool { if (Cond) @@ -60,8 +63,8 @@ Ctx->markFail(); size_t OffsetLength = OpString.size() > 2 ? OpString.size() - 2 : 0; cpp::string Offset(OffsetLength, ' '); - tlog << File << ":" << Line << ": FAILURE\n" - << Offset << "Expected: " << LHSStr << '\n' + tlog << Loc; + tlog << Offset << "Expected: " << LHSStr << '\n' << Offset << "Which is: " << describeValue(LHS) << '\n' << "To be " << OpString << ": " << RHSStr << '\n' << Offset << "Which is: " << describeValue(RHS) << '\n'; @@ -167,55 +170,49 @@ namespace internal { template bool test(RunContext *Ctx, TestCond Cond, char LHS, char RHS, - const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + const char *LHSStr, const char *RHSStr, Location Loc); template bool test(RunContext *Ctx, TestCond Cond, short LHS, short RHS, - const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + const char *LHSStr, const char *RHSStr, Location Loc); template bool test(RunContext *Ctx, TestCond Cond, int LHS, int RHS, - const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + const char *LHSStr, const char *RHSStr, Location Loc); template bool test(RunContext *Ctx, TestCond Cond, long LHS, long RHS, - const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + const char *LHSStr, const char *RHSStr, Location Loc); template bool test(RunContext *Ctx, TestCond Cond, long long LHS, long long RHS, const char *LHSStr, - const char *RHSStr, const char *File, - unsigned long Line); + const char *RHSStr, Location Loc); template bool test(RunContext *Ctx, TestCond Cond, unsigned char LHS, unsigned char RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + Location Loc); template bool test(RunContext *Ctx, TestCond Cond, unsigned short LHS, unsigned short RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + Location Loc); template bool test(RunContext *Ctx, TestCond Cond, unsigned int LHS, unsigned int RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + Location Loc); template bool test(RunContext *Ctx, TestCond Cond, unsigned long LHS, unsigned long RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + Location Loc); template bool test(RunContext *Ctx, TestCond Cond, bool LHS, bool RHS, - const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + const char *LHSStr, const char *RHSStr, Location Loc); template bool test(RunContext *Ctx, TestCond Cond, unsigned long long LHS, unsigned long long RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + Location Loc); // We cannot just use a single UInt128 specialization as that resolves to only // one type, UInt<128> or __uint128_t. We want both overloads as we want to @@ -226,67 +223,73 @@ // also. template bool test<__uint128_t>(RunContext *Ctx, TestCond Cond, __uint128_t LHS, __uint128_t RHS, const char *LHSStr, - const char *RHSStr, const char *File, - unsigned long Line); + const char *RHSStr, Location Loc); #endif -template bool test<__llvm_libc::cpp::UInt<128>>( - RunContext *Ctx, TestCond Cond, __llvm_libc::cpp::UInt<128> LHS, - __llvm_libc::cpp::UInt<128> RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); - -template bool test<__llvm_libc::cpp::UInt<192>>( - RunContext *Ctx, TestCond Cond, __llvm_libc::cpp::UInt<192> LHS, - __llvm_libc::cpp::UInt<192> RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); - -template bool test<__llvm_libc::cpp::UInt<256>>( - RunContext *Ctx, TestCond Cond, __llvm_libc::cpp::UInt<256> LHS, - __llvm_libc::cpp::UInt<256> RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); - -template bool test<__llvm_libc::cpp::UInt<320>>( - RunContext *Ctx, TestCond Cond, __llvm_libc::cpp::UInt<320> LHS, - __llvm_libc::cpp::UInt<320> RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); +template bool test<__llvm_libc::cpp::UInt<128>>(RunContext *Ctx, TestCond Cond, + __llvm_libc::cpp::UInt<128> LHS, + __llvm_libc::cpp::UInt<128> RHS, + const char *LHSStr, + const char *RHSStr, + Location Loc); + +template bool test<__llvm_libc::cpp::UInt<192>>(RunContext *Ctx, TestCond Cond, + __llvm_libc::cpp::UInt<192> LHS, + __llvm_libc::cpp::UInt<192> RHS, + const char *LHSStr, + const char *RHSStr, + Location Loc); + +template bool test<__llvm_libc::cpp::UInt<256>>(RunContext *Ctx, TestCond Cond, + __llvm_libc::cpp::UInt<256> LHS, + __llvm_libc::cpp::UInt<256> RHS, + const char *LHSStr, + const char *RHSStr, + Location Loc); + +template bool test<__llvm_libc::cpp::UInt<320>>(RunContext *Ctx, TestCond Cond, + __llvm_libc::cpp::UInt<320> LHS, + __llvm_libc::cpp::UInt<320> RHS, + const char *LHSStr, + const char *RHSStr, + Location Loc); template bool test<__llvm_libc::cpp::string_view>( RunContext *Ctx, TestCond Cond, __llvm_libc::cpp::string_view LHS, __llvm_libc::cpp::string_view RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); + Location Loc); -template bool test<__llvm_libc::cpp::string>( - RunContext *Ctx, TestCond Cond, __llvm_libc::cpp::string LHS, - __llvm_libc::cpp::string RHS, const char *LHSStr, const char *RHSStr, - const char *File, unsigned long Line); +template bool test<__llvm_libc::cpp::string>(RunContext *Ctx, TestCond Cond, + __llvm_libc::cpp::string LHS, + __llvm_libc::cpp::string RHS, + const char *LHSStr, + const char *RHSStr, Location Loc); } // namespace internal bool Test::testStrEq(const char *LHS, const char *RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { - return internal::test(Ctx, TestCond::EQ, - LHS ? cpp::string_view(LHS) : cpp::string_view(), - RHS ? cpp::string_view(RHS) : cpp::string_view(), - LHSStr, RHSStr, File, Line); + const char *RHSStr, internal::Location Loc) { + return internal::test( + Ctx, TestCond::EQ, LHS ? cpp::string_view(LHS) : cpp::string_view(), + RHS ? cpp::string_view(RHS) : cpp::string_view(), LHSStr, RHSStr, Loc); } bool Test::testStrNe(const char *LHS, const char *RHS, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { - return internal::test(Ctx, TestCond::NE, - LHS ? cpp::string_view(LHS) : cpp::string_view(), - RHS ? cpp::string_view(RHS) : cpp::string_view(), - LHSStr, RHSStr, File, Line); + const char *RHSStr, internal::Location Loc) { + return internal::test( + Ctx, TestCond::NE, LHS ? cpp::string_view(LHS) : cpp::string_view(), + RHS ? cpp::string_view(RHS) : cpp::string_view(), LHSStr, RHSStr, Loc); } bool Test::testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr, - const char *RHSStr, const char *File, unsigned long Line) { + const char *RHSStr, internal::Location Loc) { if (MatchResult) return true; Ctx->markFail(); if (!Matcher.is_silent()) { - tlog << File << ":" << Line << ": FAILURE\n" - << "Failed to match " << LHSStr << " against " << RHSStr << ".\n"; + tlog << Loc; + tlog << "Failed to match " << LHSStr << " against " << RHSStr << ".\n"; Matcher.explainError(); } return false;