diff --git a/libc/cmake/modules/LLVMLibCRules.cmake b/libc/cmake/modules/LLVMLibCRules.cmake --- a/libc/cmake/modules/LLVMLibCRules.cmake +++ b/libc/cmake/modules/LLVMLibCRules.cmake @@ -339,10 +339,9 @@ target_include_directories( ${target_name} PRIVATE - ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include - ${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include ${LIBC_SOURCE_DIR} ${LIBC_BUILD_DIR} + ${LIBC_BUILD_DIR}/include ) if(library_deps) @@ -357,7 +356,7 @@ gtest ) - target_link_libraries(${target_name} PRIVATE gtest_main gtest) + target_link_libraries(${target_name} PRIVATE LibcUnitTest LLVMSupport) add_custom_command( TARGET ${target_name} diff --git a/libc/src/string/strcat.h b/libc/src/string/strcat.h --- a/libc/src/string/strcat.h +++ b/libc/src/string/strcat.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC_STRING_STRCAT_H #define LLVM_LIBC_SRC_STRING_STRCAT_H -#include +#include "include/string.h" namespace __llvm_libc { diff --git a/libc/src/string/strcpy.h b/libc/src/string/strcpy.h --- a/libc/src/string/strcpy.h +++ b/libc/src/string/strcpy.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC_STRING_STRCPY_H #define LLVM_LIBC_SRC_STRING_STRCPY_H -#include +#include "include/string.h" namespace __llvm_libc { diff --git a/libc/src/sys/mman/mmap.h b/libc/src/sys/mman/mmap.h --- a/libc/src/sys/mman/mmap.h +++ b/libc/src/sys/mman/mmap.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC_SYS_MMAN_MMAP_H #define LLVM_LIBC_SRC_SYS_MMAN_MMAP_H -#include // For size_t and off_t +#include "include/sys/mman.h" // For size_t and off_t namespace __llvm_libc { diff --git a/libc/src/sys/mman/mmap.cpp b/libc/src/sys/mman/mmap.cpp --- a/libc/src/sys/mman/mmap.cpp +++ b/libc/src/sys/mman/mmap.cpp @@ -7,13 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/sys/mman/mmap.h" +#include "include/sys/syscall.h" // For syscall numbers. #include "src/__support/common.h" #include "src/errno/llvmlibc_errno.h" - #include "src/unistd/syscall.h" // For internal syscall function. -#include // For syscall numbers. - namespace __llvm_libc { // This function is currently linux only. It has to be refactored suitably if diff --git a/libc/src/sys/mman/munmap.h b/libc/src/sys/mman/munmap.h --- a/libc/src/sys/mman/munmap.h +++ b/libc/src/sys/mman/munmap.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC_SYS_MMAN_MUNMAP_H #define LLVM_LIBC_SRC_SYS_MMAN_MUNMAP_H -#include // For size_t +#include "include/sys/mman.h" // For size_t. namespace __llvm_libc { diff --git a/libc/src/sys/mman/munmap.cpp b/libc/src/sys/mman/munmap.cpp --- a/libc/src/sys/mman/munmap.cpp +++ b/libc/src/sys/mman/munmap.cpp @@ -7,13 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/sys/mman/munmap.h" +#include "include/sys/syscall.h" // For syscall numbers. #include "src/__support/common.h" #include "src/errno/llvmlibc_errno.h" - #include "src/unistd/syscall.h" // For internal syscall function. -#include // For syscall numbers. - namespace __llvm_libc { // This function is currently linux only. It has to be refactored suitably if diff --git a/libc/test/config/linux/x86_64/syscall_test.cpp b/libc/test/config/linux/x86_64/syscall_test.cpp --- a/libc/test/config/linux/x86_64/syscall_test.cpp +++ b/libc/test/config/linux/x86_64/syscall_test.cpp @@ -7,8 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/unistd/syscall.h" - -#include "gtest/gtest.h" +#include "utils/UnitTest/Test.h" #include diff --git a/libc/test/src/errno/errno_test.cpp b/libc/test/src/errno/errno_test.cpp --- a/libc/test/src/errno/errno_test.cpp +++ b/libc/test/src/errno/errno_test.cpp @@ -7,8 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/errno/llvmlibc_errno.h" - -#include "gtest/gtest.h" +#include "utils/UnitTest/Test.h" TEST(ErrnoTest, Basic) { int test_val = 123; diff --git a/libc/test/src/string/strcat_test.cpp b/libc/test/src/string/strcat_test.cpp --- a/libc/test/src/string/strcat_test.cpp +++ b/libc/test/src/string/strcat_test.cpp @@ -6,25 +6,23 @@ // //===----------------------------------------------------------------------===// -#include - #include "src/string/strcat.h" -#include "gtest/gtest.h" +#include "utils/UnitTest/Test.h" TEST(StrCatTest, EmptyDest) { - std::string abc = "abc"; + const char *abc = "abc"; char dest[4]; dest[0] = '\0'; - char *result = __llvm_libc::strcat(dest, abc.c_str()); + char *result = __llvm_libc::strcat(dest, abc); ASSERT_EQ(dest, result); - ASSERT_EQ(std::string(dest), abc); - ASSERT_EQ(std::string(dest).size(), abc.size()); + ASSERT_STREQ(dest, result); + ASSERT_STREQ(dest, abc); } TEST(StrCatTest, NonEmptyDest) { - std::string abc = "abc"; + const char *abc = "abc"; char dest[7]; dest[0] = 'x'; @@ -32,8 +30,8 @@ dest[2] = 'z'; dest[3] = '\0'; - char *result = __llvm_libc::strcat(dest, abc.c_str()); + char *result = __llvm_libc::strcat(dest, abc); ASSERT_EQ(dest, result); - ASSERT_EQ(std::string(dest), std::string("xyz") + abc); - ASSERT_EQ(std::string(dest).size(), abc.size() + 3); + ASSERT_STREQ(dest, result); + ASSERT_STREQ(dest, "xyzabc"); } diff --git a/libc/test/src/string/strcpy_test.cpp b/libc/test/src/string/strcpy_test.cpp --- a/libc/test/src/string/strcpy_test.cpp +++ b/libc/test/src/string/strcpy_test.cpp @@ -6,31 +6,29 @@ // //===----------------------------------------------------------------------===// -#include - #include "src/string/strcpy.h" -#include "gtest/gtest.h" +#include "utils/UnitTest/Test.h" TEST(StrCpyTest, EmptyDest) { - std::string abc = "abc"; + const char *abc = "abc"; char dest[4]; - char *result = __llvm_libc::strcpy(dest, abc.c_str()); + char *result = __llvm_libc::strcpy(dest, abc); ASSERT_EQ(dest, result); - ASSERT_EQ(std::string(dest), abc); - ASSERT_EQ(std::string(dest).size(), abc.size()); + ASSERT_STREQ(dest, result); + ASSERT_STREQ(dest, abc); } TEST(StrCpyTest, OffsetDest) { - std::string abc = "abc"; + const char *abc = "abc"; char dest[7]; dest[0] = 'x'; dest[1] = 'y'; dest[2] = 'z'; - char *result = __llvm_libc::strcpy(dest + 3, abc.c_str()); + char *result = __llvm_libc::strcpy(dest + 3, abc); ASSERT_EQ(dest + 3, result); - ASSERT_EQ(std::string(dest), std::string("xyz") + abc); - ASSERT_EQ(std::string(dest).size(), abc.size() + 3); + ASSERT_STREQ(dest + 3, result); + ASSERT_STREQ(dest, "xyzabc"); } diff --git a/libc/test/src/sys/mman/CMakeLists.txt b/libc/test/src/sys/mman/CMakeLists.txt --- a/libc/test/src/sys/mman/CMakeLists.txt +++ b/libc/test/src/sys/mman/CMakeLists.txt @@ -7,6 +7,8 @@ SRCS mmap_test.cpp DEPENDS + errno_h + sys_mman_h mmap munmap __errno_location diff --git a/libc/test/src/sys/mman/mmap_test.cpp b/libc/test/src/sys/mman/mmap_test.cpp --- a/libc/test/src/sys/mman/mmap_test.cpp +++ b/libc/test/src/sys/mman/mmap_test.cpp @@ -6,14 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/errno.h" +#include "include/sys/mman.h" #include "src/errno/llvmlibc_errno.h" #include "src/sys/mman/mmap.h" #include "src/sys/mman/munmap.h" - -#include "gtest/gtest.h" - -#include "errno.h" -#include "sys/mman.h" +#include "utils/UnitTest/Test.h" TEST(MMapTest, NoError) { size_t alloc_size = 128; diff --git a/libc/utils/CMakeLists.txt b/libc/utils/CMakeLists.txt --- a/libc/utils/CMakeLists.txt +++ b/libc/utils/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(HdrGen) +add_subdirectory(UnitTest) diff --git a/libc/utils/UnitTest/CMakeLists.txt b/libc/utils/UnitTest/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/utils/UnitTest/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_library( + LibcUnitTest + Test.cpp + Test.h +) diff --git a/libc/utils/UnitTest/Test.h b/libc/utils/UnitTest/Test.h new file mode 100644 --- /dev/null +++ b/libc/utils/UnitTest/Test.h @@ -0,0 +1,217 @@ +//===------------------ Base class for libc unittests -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This file should stricly not include any other file. Not even standard +// library headers. + +namespace llvm_libc { +namespace testing { + +// We define our own EnableIf and IsIntegerType traits because we do not want to +// include even the standard header . +template struct EnableIf; +template struct EnableIf { typedef T Type; }; + +template +using EnableIfType = typename EnableIf::Type; + +template struct IsIntegerType { + static const bool Value = false; +}; + +template <> struct IsIntegerType { static const bool Value = true; }; +template <> struct IsIntegerType { + static const bool Value = true; +}; + +template <> struct IsIntegerType { static const bool Value = true; }; +template <> struct IsIntegerType { + static const bool Value = true; +}; + +template <> struct IsIntegerType { static const bool Value = true; }; +template <> struct IsIntegerType { + static const bool Value = true; +}; + +template <> struct IsIntegerType { static const bool Value = true; }; +template <> struct IsIntegerType { + static const bool Value = true; +}; + +template <> struct IsIntegerType { static const bool Value = true; }; +template <> struct IsIntegerType { + static const bool Value = true; +}; + +template struct IsPointerType; + +template struct IsPointerType { + static const bool Value = true; +}; + +class RunContext; + +// Only the following conditions are supported. Notice that we do not have +// a TRUE or FALSE condition. That is because, C library funtions do not +// return, but use integral return values to indicate true or false +// conditions. Hence, it is more appropriate to use the other comparison +// condtions for such cases. +enum TestCondition { + Cond_None, + Cond_EQ, + Cond_NE, + Cond_LT, + Cond_LE, + Cond_GT, + Cond_GE, +}; + +namespace internal { + +template +bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, ValType RHS, + const char *LHSStr, const char *RHSStr, const char *File, + unsigned long Line); + +} // namespace internal + +// 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; + +public: + virtual ~Test() {} + virtual void SetUp() {} + virtual void TearDown() {} + + static int runTests(); + +protected: + static void addTest(Test *T); + + // We make use of a template function, with |LHS| and |RHS| as explicit + // parameters, for enhanced type checking. Other gtest like test unittest + // frameworks have a similar functions which takes a boolean argument + // instead of the explicit |LHS| and |RHS| arguments. This boolean argument + // is the result of the |Cond| operation on |LHS| and |RHS|. Though not bad, + // mismatched |LHS| and |RHS| types can potentially succeed because of type + // promotion. + template ::Value, ValType> = 0> + static bool test(RunContext &Ctx, TestCondition 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); + } + + template ::Value, ValType> = nullptr> + static bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, + ValType RHS, const char *LHSStr, const char *RHSStr, + const char *File, unsigned long Line) { + return internal::test(Ctx, Cond, (unsigned long long)LHS, + (unsigned long long)RHS, LHSStr, RHSStr, File, Line); + } + + static bool testStrEq(RunContext &Ctx, const char *LHS, const char *RHS, + const char *LHSStr, const char *RHSStr, + const char *File, unsigned long Line); + + static bool testStrNe(RunContext &Ctx, const char *LHS, const char *RHS, + const char *LHSStr, const char *RHSStr, + const char *File, unsigned long Line); + +private: + virtual void Run(RunContext &Ctx) = 0; + virtual const char *getName() const = 0; + + static Test *Start; + static Test *End; +}; + +} // namespace testing +} // namespace llvm_libc + +#define TEST(SuiteName, TestName) \ + class SuiteName##_##TestName : public llvm_libc::testing::Test { \ + public: \ + SuiteName##_##TestName() { addTest(this); } \ + void Run(llvm_libc::testing::RunContext &) override; \ + const char *getName() const override { return #SuiteName "." #TestName; } \ + }; \ + SuiteName##_##TestName SuiteName##_##TestName##_Instance; \ + void SuiteName##_##TestName::Run(llvm_libc::testing::RunContext &Ctx) + +#define TEST_F(SuiteClass, TestName) \ + class SuiteClass##_##TestName : public SuiteClass { \ + public: \ + SuiteClass##_##TestName() { addTest(this); } \ + void Run(llvm_libc::testing::RunContext &) override; \ + const char *getName() const override { return #SuiteClass "." #TestName; } \ + }; \ + SuiteClass##_##TestName SuiteClass##_##TestName##_Instance; \ + void SuiteClass##_##TestName::Run(llvm_libc::testing::RunContext &Ctx) + +#define EXPECT_EQ(LHS, RHS) \ + llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_EQ, (LHS), \ + (RHS), #LHS, #RHS, __FILE__, __LINE__) +#define ASSERT_EQ(LHS, RHS) \ + if (!EXPECT_EQ(LHS, RHS)) \ + return + +#define EXPECT_NE(LHS, RHS) \ + llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_NE, (LHS), \ + (RHS), #LHS, #RHS, __FILE__, __LINE__) +#define ASSERT_NE(LHS, RHS) \ + if (!EXPECT_NE(LHS, RHS)) \ + return + +#define EXPECT_LT(LHS, RHS) \ + llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_LT, (LHS), \ + (RHS), #LHS, #RHS, __FILE__, __LINE__) +#define ASSERT_LT(LHS, RHS) \ + if (!EXPECT_LT(LHS, RHS)) \ + return + +#define EXPECT_LE(LHS, RHS) \ + llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_LE, (LHS), \ + (RHS), #LHS, #RHS, __FILE__, __LINE__) +#define ASSERT_LE(LHS, RHS) \ + if (!EXPECT_LE(LHS, RHS)) \ + return + +#define EXPECT_GT(LHS, RHS) \ + llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_GT, (LHS), \ + (RHS), #LHS, #RHS, __FILE__, __LINE__) +#define ASSERT_GT(LHS, RHS) \ + if (!EXPECT_GT(LHS, RHS)) \ + return + +#define EXPECT_GE(LHS, RHS) \ + llvm_libc::testing::Test::test(Ctx, llvm_libc::testing::Cond_GE, (LHS), \ + (RHS), #LHS, #RHS, __FILE__, __LINE__) +#define ASSERT_GE(LHS, RHS) \ + if (!EXPECT_GE(LHS, RHS)) \ + return + +#define EXPECT_STREQ(LHS, RHS) \ + llvm_libc::testing::Test::testStrEq(Ctx, (LHS), (RHS), #LHS, #RHS, __FILE__, \ + __LINE__) +#define ASSERT_STREQ(LHS, RHS) \ + if (!EXPECT_STREQ(LHS, RHS)) \ + return + +#define EXPECT_STRNE(LHS, RHS) \ + llvm_libc::testing::Test::testStrNe(Ctx, (LHS), (RHS), #LHS, #RHS, __FILE__, \ + __LINE__) +#define ASSERT_STRNE(LHS, RHS) \ + if (!EXPECT_STRNE(LHS, RHS)) \ + return diff --git a/libc/utils/UnitTest/Test.cpp b/libc/utils/UnitTest/Test.cpp new file mode 100644 --- /dev/null +++ b/libc/utils/UnitTest/Test.cpp @@ -0,0 +1,237 @@ +//===--------- Implementation of the base class for libc unittests --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Test.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm_libc { +namespace testing { + +// This need not be a class as all it has is a single read-write state variable. +// But, we make it class as then its implementation can be hidden from the +// header file. +class RunContext { +public: + enum RunResult { Result_Pass = 1, Result_Fail = 2 }; + + RunResult status() const { return Status; } + + void markFail() { Status = Result_Fail; } + +private: + RunResult Status = Result_Pass; +}; + +namespace internal { + +template +bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, ValType RHS, + const char *LHSStr, const char *RHSStr, const char *File, + unsigned long Line) { + if (Cond == Cond_EQ) { + if (LHS == RHS) + return true; + + Ctx.markFail(); + llvm::outs() << File << ":" << Line << ": FAILURE\n" + << " Expected: " << LHSStr << '\n' + << " Which is: " << LHS << '\n' + << "To be equal to: " << RHSStr << '\n' + << " Which is: " << RHS << '\n'; + + return false; + } + + if (Cond == Cond_NE) { + if (LHS != RHS) + return true; + + Ctx.markFail(); + llvm::outs() << File << ":" << Line << ": FAILURE\n" + << " Expected: " << LHSStr << '\n' + << " Which is: " << LHS << '\n' + << "To be not equal to: " << RHSStr << '\n' + << " Which is: " << RHS << '\n'; + return false; + } + + if (Cond == Cond_LT) { + if (LHS < RHS) + return true; + + Ctx.markFail(); + llvm::outs() << File << ":" << Line << ": FAILURE\n" + << " Expected: " << LHSStr << '\n' + << " Which is: " << LHS << '\n' + << "To be less than: " << RHSStr << '\n' + << " Which is: " << RHS << '\n'; + return false; + } + + if (Cond == Cond_LE) { + if (LHS <= RHS) + return true; + + Ctx.markFail(); + llvm::outs() << File << ":" << Line << ": FAILURE\n" + << " Expected: " << LHSStr << '\n' + << " Which is: " << LHS << '\n' + << "To be less than or equal to: " << RHSStr << '\n' + << " Which is: " << RHS << '\n'; + return false; + } + + if (Cond == Cond_GT) { + if (LHS > RHS) + return true; + + Ctx.markFail(); + llvm::outs() << File << ":" << Line << ": FAILURE\n" + << " Expected: " << LHSStr << '\n' + << " Which is: " << LHS << '\n' + << "To be greater than: " << RHSStr << '\n' + << " Which is: " << RHS << '\n'; + return false; + } + + if (Cond == Cond_GE) { + if (LHS >= RHS) + return true; + + Ctx.markFail(); + llvm::outs() << File << ":" << Line << ": FAILURE\n" + << " Expected: " << LHSStr << '\n' + << " Which is: " << LHS << '\n' + << "To be greater than or equal to: " << RHSStr << '\n' + << " Which is: " << RHS << '\n'; + return false; + } + + Ctx.markFail(); + llvm::outs() << "Unexpected test condition.\n"; + return false; +} + +} // namespace internal + +Test *Test::Start = nullptr; +Test *Test::End = nullptr; + +void Test::addTest(Test *T) { + if (End == nullptr) { + Start = T; + End = T; + return; + } + + End->Next = T; + End = T; +} + +int Test::runTests() { + int TestCount = 0; + int FailCount = 0; + for (Test *T = Start; T != nullptr; T = T->Next, ++TestCount) { + const char *TestName = T->getName(); + llvm::outs() << "[ RUN ] " << TestName << '\n'; + RunContext Ctx; + T->SetUp(); + T->Run(Ctx); + T->TearDown(); + auto Result = Ctx.status(); + if (Result == RunContext::Result_Fail) { + llvm::outs() << "[ FAILED ] " << TestName << '\n'; + ++FailCount; + } else if (Result == RunContext::Result_Pass) { + llvm::outs() << "[ OK ] " << TestName << '\n'; + } else { + llvm::outs() << "Unexpected result after running " << TestName << '\n'; + } + } + + llvm::outs() << "Ran " << TestCount << " tests. " + << " PASS: " << TestCount - FailCount << ' ' + << " FAIL: " << FailCount << '\n'; + + return FailCount > 0 ? 1 : 0; +} + +template bool Test::test(RunContext &Ctx, TestCondition Cond, char LHS, + char RHS, const char *LHSStr, + const char *RHSStr, const char *File, + unsigned long Line); + +template bool Test::test(RunContext &Ctx, TestCondition Cond, + short LHS, short RHS, const char *LHSStr, + const char *RHSStr, const char *File, + unsigned long Line); + +template bool Test::test(RunContext &Ctx, TestCondition Cond, int LHS, + int RHS, const char *LHSStr, + const char *RHSStr, const char *File, + unsigned long Line); + +template bool Test::test(RunContext &Ctx, TestCondition Cond, long LHS, + long RHS, const char *LHSStr, + const char *RHSStr, const char *File, + unsigned long Line); + +template bool Test::test(RunContext &Ctx, TestCondition Cond, + long long LHS, long long RHS, + const char *LHSStr, const char *RHSStr, + const char *File, unsigned long Line); + +template bool Test::test(RunContext &Ctx, TestCondition Cond, + unsigned char LHS, unsigned char RHS, + const char *LHSStr, + const char *RHSStr, const char *File, + unsigned long Line); + +template bool +Test::test(RunContext &Ctx, TestCondition Cond, + unsigned short LHS, unsigned short RHS, + const char *LHSStr, const char *RHSStr, + const char *File, unsigned long Line); + +template bool Test::test(RunContext &Ctx, TestCondition Cond, + unsigned int LHS, unsigned int RHS, + const char *LHSStr, + const char *RHSStr, const char *File, + unsigned long Line); + +template bool Test::test(RunContext &Ctx, TestCondition Cond, + unsigned long LHS, unsigned long RHS, + const char *LHSStr, + const char *RHSStr, const char *File, + unsigned long Line); + +template bool Test::test( + RunContext &Ctx, TestCondition Cond, unsigned long long LHS, + unsigned long long RHS, const char *LHSStr, const char *RHSStr, + const char *File, unsigned long Line); + +bool Test::testStrEq(RunContext &Ctx, const char *LHS, const char *RHS, + const char *LHSStr, const char *RHSStr, const char *File, + unsigned long Line) { + return internal::test(Ctx, Cond_EQ, llvm::StringRef(LHS), + llvm::StringRef(RHS), LHSStr, RHSStr, File, Line); +} + +bool Test::testStrNe(RunContext &Ctx, const char *LHS, const char *RHS, + const char *LHSStr, const char *RHSStr, const char *File, + unsigned long Line) { + return internal::test(Ctx, Cond_NE, llvm::StringRef(LHS), + llvm::StringRef(RHS), LHSStr, RHSStr, File, Line); +} + +} // namespace testing +} // namespace llvm_libc + +int main() { return llvm_libc::testing::Test::runTests(); }