From 7c02dc22e487637abe752939c0e82d36be9921df Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Fri, 16 Apr 2021 09:18:03 +0000 Subject: [PATCH] [libc] Extends the testing framework to support typed test This patch provides `TYPED_TEST` and `TYPED_TEST_F` (similar in functionnality to gtest). This is needed to extensively test building blocks for memory functions. Example for `TYPED_TEST_F`: ``` template class LlvmLibcMyTestFixture : public testing::Test {}; using Types = testing::TypeList; TYPED_TEST_F(LlvmLibcMyTestFixture, Simple, Types) { EXPECT_LE(sizeof(ParamType), 8UL); } ``` Example for `TYPED_TEST`: ``` using Types = testing::TypeList; TYPED_TEST(LlvmLibcMyTest, Simple, Types) { EXPECT_LE(sizeof(ParamType), 8UL); } ``` `ParamType` is displayed as fully qualified canonical type which can be difficult to read, the user can provide a more readable name by using the `REGISTER_TYPE_NAME` macro. Differential Revision: https://reviews.llvm.org/D100631 --- libc/utils/UnitTest/LibcTest.h | 136 +++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 6 deletions(-) diff --git a/libc/utils/UnitTest/LibcTest.h b/libc/utils/UnitTest/LibcTest.h index a0ecf5a0b586..798acfe09ffe 100644 --- a/libc/utils/UnitTest/LibcTest.h +++ b/libc/utils/UnitTest/LibcTest.h @@ -131,22 +131,146 @@ class Test { static Test *End; }; -} // namespace testing -} // namespace __llvm_libc - -namespace __llvm_libc { namespace internal { + constexpr bool same_prefix(char const *lhs, char const *rhs, int const len) { for (int i = 0; (*lhs || *rhs) && (i < len); ++lhs, ++rhs, ++i) if (*lhs != *rhs) return false; return true; } + +constexpr bool valid_prefix(char const *lhs) { + return same_prefix(lhs, "LlvmLibc", 8); +} + +// 'str' is a null terminated string of the form +// "const char *__llvm_libc::testing::internal::GetTypeName() [ParamType = XXX]" +// We return the substring that start at character '[' or a default message. +constexpr char const *GetPrettyFunctionParamType(char const *str) { + for (const char *ptr = str; *ptr != '\0'; ++ptr) + if (*ptr == '[') + return ptr; + return "UNSET : declare with REGISTER_TYPE_NAME"; +} + +// This function recovers ParamType at compile time by using __PRETTY_FUNCTION__ +// It can be customized by using the REGISTER_TYPE_NAME macro below. +template static constexpr const char *GetTypeName() { + return GetPrettyFunctionParamType(__PRETTY_FUNCTION__); +} + +template +static inline void GenerateName(char *buffer, int buffer_size, + const char *prefix) { + if (buffer_size == 0) + return; + + // Make sure string is null terminated. + --buffer_size; + buffer[buffer_size] = '\0'; + + const auto AppendChar = [&](char c) { + if (buffer_size > 0) { + *buffer = c; + ++buffer; + --buffer_size; + } + }; + const auto AppendStr = [&](const char *str) { + for (; str && *str != '\0'; ++str) + AppendChar(*str); + }; + + AppendStr(prefix); + AppendChar(' '); + AppendStr(GetTypeName()); + AppendChar('\0'); +} + +// TestCreator implements a linear hierarchy of test instances, effectively +// instanciating all tests with Types in a single object. +template