diff --git a/libc/utils/UnitTest/LibcTest.h b/libc/utils/UnitTest/LibcTest.h --- a/libc/utils/UnitTest/LibcTest.h +++ b/libc/utils/UnitTest/LibcTest.h @@ -131,22 +131,145 @@ 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__ +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