diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake index 418551f137e44..1abf21dda1249 100644 --- a/libc/cmake/modules/LLVMLibCTestRules.cmake +++ b/libc/cmake/modules/LLVMLibCTestRules.cmake @@ -374,8 +374,9 @@ function(create_libc_unittest fq_target_name) ) # LibcUnitTest should not depend on anything in LINK_LIBRARIES. + list(APPEND link_libraries LibcTest.unit) if(NOT LIBC_UNITTEST_C_TEST) - list(APPEND link_libraries LibcDeathTestExecutors.unit LibcTest.unit) + list(APPEND link_libraries LibcDeathTestExecutors.unit) endif() target_link_libraries(${fq_build_target_name} PRIVATE ${link_libraries}) diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt index 1732473e355dc..9b244a9003d82 100644 --- a/libc/test/UnitTest/CMakeLists.txt +++ b/libc/test/UnitTest/CMakeLists.txt @@ -73,10 +73,12 @@ add_unittest_framework_library( LibcTest SRCS CmakeFilePath.cpp + LibcCTest.cpp LibcTest.cpp LibcTestMain.cpp TestLogger.cpp HDRS + LibcCTest.h LibcTest.h Test.h TestLogger.h diff --git a/libc/test/UnitTest/LibcCTest.cpp b/libc/test/UnitTest/LibcCTest.cpp new file mode 100644 index 0000000000000..8e19f7dd30227 --- /dev/null +++ b/libc/test/UnitTest/LibcCTest.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Helpers for libc C unittests. +/// +//===----------------------------------------------------------------------===// + +#include "test/UnitTest/LibcCTest.h" +#include "test/UnitTest/LibcTest.h" + +namespace { +class CTest : public LIBC_NAMESPACE::testing::Test { +public: + CTest() { addTest(this); } + void Run() override { libc_c_test_run(); } + const char *getName() const override { return LIBC_C_TEST_NAME; } +}; +} // namespace + +static CTest c_test_instance; + +extern "C" void libc_c_test_anchor() {} + +extern "C" void libc_c_test_fail(const char *cond, int expected, + const char *file, int line) { + LIBC_NAMESPACE::testing::internal::test( + LIBC_NAMESPACE::testing::TestCond::EQ, !expected, + static_cast(expected), cond, expected ? "true" : "false", + LIBC_NAMESPACE::testing::internal::Location(file, line)); +} diff --git a/libc/test/UnitTest/LibcCTest.h b/libc/test/UnitTest/LibcCTest.h new file mode 100644 index 0000000000000..cac8a271e7d88 --- /dev/null +++ b/libc/test/UnitTest/LibcCTest.h @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// C wrappers for libc unittests +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_TEST_UNITTEST_LIBCCTEST_H +#define LLVM_LIBC_TEST_UNITTEST_LIBCCTEST_H + +#include "include/__llvm-libc-common.h" + +__BEGIN_C_DECLS + +// These symbols are implementation details of the test macros. Do not reference +// them directly. +void libc_c_test_fail(const char *cond, int expected, const char *file, + int line); +extern const char LIBC_C_TEST_NAME[]; +void libc_c_test_run(void); +void libc_c_test_anchor(void); + +__END_C_DECLS + +// Use LibcTest.h in C++ code. +#ifndef __cplusplus +#define TEST(name) \ + const char LIBC_C_TEST_NAME[] = "LlvmLibcCTest." #name; \ + void libc_c_test_run_impl(void); \ + void libc_c_test_run(void) { \ + libc_c_test_anchor(); /* Force a reference to the C test framework. */ \ + libc_c_test_run_impl(); \ + } \ + void libc_c_test_run_impl(void) +#define LIBC_C_TEST_SCAFFOLDING_(cond, expected, ret_or_empty) \ + do { \ + if (!(cond) != !(expected)) { \ + libc_c_test_fail(#cond, (expected), __FILE__, __LINE__); \ + ret_or_empty; \ + } \ + } while (0) + +#define EXPECT_TRUE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 1, ) +#define ASSERT_TRUE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 1, return) + +#define EXPECT_FALSE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 0, ) +#define ASSERT_FALSE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 0, return) +#endif + +#endif // LLVM_LIBC_TEST_UNITTEST_LIBCCTEST_H diff --git a/libc/test/include/fpclassify_test.c b/libc/test/include/fpclassify_test.c index d52d999301115..0d265552b29ed 100644 --- a/libc/test/include/fpclassify_test.c +++ b/libc/test/include/fpclassify_test.c @@ -6,20 +6,18 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef fpclassify #error "fpclassify macro is not defined" #else -int main(void) { - assert(fpclassify(1.819f) == FP_NORMAL); - assert(fpclassify(-1.726) == FP_NORMAL); - assert(fpclassify(1.426L) == FP_NORMAL); - assert(fpclassify(-0.0f) == FP_ZERO); - assert(fpclassify(0.0) == FP_ZERO); - assert(fpclassify(-0.0L) == FP_ZERO); - return 0; +TEST(fpclassify) { + EXPECT_TRUE(fpclassify(1.819f) == FP_NORMAL); + EXPECT_TRUE(fpclassify(-1.726) == FP_NORMAL); + EXPECT_TRUE(fpclassify(1.426L) == FP_NORMAL); + EXPECT_TRUE(fpclassify(-0.0f) == FP_ZERO); + EXPECT_TRUE(fpclassify(0.0) == FP_ZERO); + EXPECT_TRUE(fpclassify(-0.0L) == FP_ZERO); } #endif diff --git a/libc/test/include/isfinite_test.c b/libc/test/include/isfinite_test.c index 9cc897db7c040..1cece5c9fe605 100644 --- a/libc/test/include/isfinite_test.c +++ b/libc/test/include/isfinite_test.c @@ -6,17 +6,15 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef isfinite #error "isfinite macro is not defined" #else -int main(void) { - assert(isfinite(1.0f)); - assert(isfinite(1.0)); - assert(isfinite(1.0L)); - return 0; +TEST(isfinite) { + EXPECT_TRUE(isfinite(1.0f)); + EXPECT_TRUE(isfinite(1.0)); + EXPECT_TRUE(isfinite(1.0L)); } #endif diff --git a/libc/test/include/isinf_test.c b/libc/test/include/isinf_test.c index 7dc6ce5579263..d818c7df66bdc 100644 --- a/libc/test/include/isinf_test.c +++ b/libc/test/include/isinf_test.c @@ -6,17 +6,15 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef isinf #error "isinf macro is not defined" #else -int main(void) { - assert(!isinf(1.0f)); - assert(!isinf(1.0)); - assert(!isinf(1.0L)); - return 0; +TEST(isinf) { + EXPECT_FALSE(isinf(1.0f)); + EXPECT_FALSE(isinf(1.0)); + EXPECT_FALSE(isinf(1.0L)); } #endif diff --git a/libc/test/include/isnan_test.c b/libc/test/include/isnan_test.c index 2234c2b2b37ad..137be638c91f2 100644 --- a/libc/test/include/isnan_test.c +++ b/libc/test/include/isnan_test.c @@ -6,17 +6,15 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef isnan #error "isnan macro is not defined" #else -int main(void) { - assert(!isnan(1.0f)); - assert(!isnan(1.0)); - assert(!isnan(1.0L)); - return 0; +TEST(isnan) { + EXPECT_FALSE(isnan(1.0f)); + EXPECT_FALSE(isnan(1.0)); + EXPECT_FALSE(isnan(1.0L)); } #endif diff --git a/libc/test/include/isnormal_test.c b/libc/test/include/isnormal_test.c index 9f576d5cb0713..7d3df67fe3593 100644 --- a/libc/test/include/isnormal_test.c +++ b/libc/test/include/isnormal_test.c @@ -6,20 +6,18 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef isnormal #error "isnormal macro is not defined" #else -int main(void) { - assert(isnormal(1.819f) == 1); - assert(isnormal(-1.726) == 1); - assert(isnormal(1.426L) == 1); - assert(isnormal(-0.0f) == 0); - assert(isnormal(0.0) == 0); - assert(isnormal(-0.0L) == 0); - return 0; +TEST(isnormal) { + EXPECT_TRUE(isnormal(1.819f) == 1); + EXPECT_TRUE(isnormal(-1.726) == 1); + EXPECT_TRUE(isnormal(1.426L) == 1); + EXPECT_TRUE(isnormal(-0.0f) == 0); + EXPECT_TRUE(isnormal(0.0) == 0); + EXPECT_TRUE(isnormal(-0.0L) == 0); } #endif diff --git a/libc/test/include/issubnormal_test.c b/libc/test/include/issubnormal_test.c index b5dea843bce89..ccaee8081ea0f 100644 --- a/libc/test/include/issubnormal_test.c +++ b/libc/test/include/issubnormal_test.c @@ -6,19 +6,17 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef issubnormal #error "issubnormal macro is not defined" #else -int main(void) { - assert(issubnormal(1.819f) == 0); - assert(issubnormal(-1.726) == 0); - assert(issubnormal(1.426L) == 0); - assert(issubnormal(1e-308) == 1); - assert(issubnormal(-1e-308) == 1); - return 0; +TEST(issubnormal) { + EXPECT_TRUE(issubnormal(1.819f) == 0); + EXPECT_TRUE(issubnormal(-1.726) == 0); + EXPECT_TRUE(issubnormal(1.426L) == 0); + EXPECT_TRUE(issubnormal(1e-308) == 1); + EXPECT_TRUE(issubnormal(-1e-308) == 1); } #endif diff --git a/libc/test/include/iszero_test.c b/libc/test/include/iszero_test.c index daffde50cdff5..0baee520f345a 100644 --- a/libc/test/include/iszero_test.c +++ b/libc/test/include/iszero_test.c @@ -6,20 +6,18 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef iszero #error "iszero macro is not defined" #else -int main(void) { - assert(iszero(1.0f) == 0); - assert(iszero(1.0) == 0); - assert(iszero(1.0L) == 0); - assert(iszero(0.0f) == 1); - assert(iszero(0.0) == 1); - assert(iszero(0.0L) == 1); - return 0; +TEST(iszero) { + EXPECT_TRUE(iszero(1.0f) == 0); + EXPECT_TRUE(iszero(1.0) == 0); + EXPECT_TRUE(iszero(1.0L) == 0); + EXPECT_TRUE(iszero(0.0f) == 1); + EXPECT_TRUE(iszero(0.0) == 1); + EXPECT_TRUE(iszero(0.0L) == 1); } #endif diff --git a/libc/test/include/math_constants_test.c b/libc/test/include/math_constants_test.c index eb497a9d8a50a..ae043aa9e3648 100644 --- a/libc/test/include/math_constants_test.c +++ b/libc/test/include/math_constants_test.c @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-macros.h" +#include "test/UnitTest/LibcCTest.h" #define IS_DOUBLE(X) _Generic((X), double: 1, default: 0) @@ -15,9 +16,8 @@ #ifndef M_PI #error "M_PI macro is not defined" #else -int main(void) { +TEST(math_constants) { _Static_assert(IS_DOUBLE(M_PI), "M_PI is not of double type."); _Static_assert(IS_FLOAT(M_PIf), "M_PIf is not of float type."); - return 0; } #endif diff --git a/libc/test/include/signbit_test.c b/libc/test/include/signbit_test.c index 2f25624ea8026..81702260ab476 100644 --- a/libc/test/include/signbit_test.c +++ b/libc/test/include/signbit_test.c @@ -6,20 +6,18 @@ // //===----------------------------------------------------------------------===// #include "include/llvm-libc-macros/math-function-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" // check if macro is defined #ifndef signbit #error "signbit macro is not defined" #else -int main(void) { - assert(!signbit(1.0f)); - assert(!signbit(1.0)); - assert(!signbit(1.0L)); - assert(signbit(-1.0f)); - assert(signbit(-1.0)); - assert(signbit(-1.0L)); - return 0; +TEST(signbit) { + EXPECT_FALSE(signbit(1.0f)); + EXPECT_FALSE(signbit(1.0)); + EXPECT_FALSE(signbit(1.0L)); + EXPECT_TRUE(signbit(-1.0f)); + EXPECT_TRUE(signbit(-1.0)); + EXPECT_TRUE(signbit(-1.0L)); } #endif diff --git a/libc/test/include/stdbit_test.c b/libc/test/include/stdbit_test.c index 207609ee1dd00..3f444ec70b229 100644 --- a/libc/test/include/stdbit_test.c +++ b/libc/test/include/stdbit_test.c @@ -23,19 +23,18 @@ #include "stdbit_stub.h" #include "include/llvm-libc-macros/stdbit-macros.h" - -#include +#include "test/UnitTest/LibcCTest.h" #define CHECK_FUNCTION(FUNC_NAME, VAL) \ do { \ - assert(FUNC_NAME((unsigned char)0U) == VAL##AU); \ - assert(FUNC_NAME((unsigned short)0U) == VAL##BU); \ - assert(FUNC_NAME(0U) == VAL##CU); \ - assert(FUNC_NAME(0UL) == VAL##DU); \ - assert(FUNC_NAME(0ULL) == VAL##EU); \ + EXPECT_TRUE(FUNC_NAME((unsigned char)0U) == VAL##AU); \ + EXPECT_TRUE(FUNC_NAME((unsigned short)0U) == VAL##BU); \ + EXPECT_TRUE(FUNC_NAME(0U) == VAL##CU); \ + EXPECT_TRUE(FUNC_NAME(0UL) == VAL##DU); \ + EXPECT_TRUE(FUNC_NAME(0ULL) == VAL##EU); \ } while (0) -int main(void) { +TEST(stdbit) { CHECK_FUNCTION(stdc_leading_zeros, 0xA); CHECK_FUNCTION(stdc_leading_ones, 0xB); CHECK_FUNCTION(stdc_trailing_zeros, 0xC); @@ -47,15 +46,13 @@ int main(void) { CHECK_FUNCTION(stdc_count_zeros, 0x2); CHECK_FUNCTION(stdc_count_ones, 0x3); - assert(!stdc_has_single_bit((unsigned char)1U)); - assert(!stdc_has_single_bit((unsigned short)1U)); - assert(!stdc_has_single_bit(1U)); - assert(!stdc_has_single_bit(1UL)); - assert(!stdc_has_single_bit(1ULL)); + EXPECT_FALSE(stdc_has_single_bit((unsigned char)1U)); + EXPECT_FALSE(stdc_has_single_bit((unsigned short)1U)); + EXPECT_FALSE(stdc_has_single_bit(1U)); + EXPECT_FALSE(stdc_has_single_bit(1UL)); + EXPECT_FALSE(stdc_has_single_bit(1ULL)); CHECK_FUNCTION(stdc_bit_width, 0x4); CHECK_FUNCTION(stdc_bit_floor, 0x5); CHECK_FUNCTION(stdc_bit_ceil, 0x6); - - return 0; } diff --git a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel index 7d25fe869e193..742261cfbe6cc 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel @@ -82,6 +82,16 @@ libc_test_library( alwayslink = True, ) +libc_test_library( + name = "LibcCTest", + srcs = ["LibcCTest.cpp"], + hdrs = ["LibcCTest.h"], + deps = [ + ":LibcUnitTest", + "//libc:public_headers_deps", + ], +) + libc_test_library( name = "fp_test_helpers", srcs = [ diff --git a/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel index 9be937e37a2ad..dcaf655c5b5c9 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel @@ -68,7 +68,7 @@ libc_test( libc_test( name = "fpclassify_c_test", srcs = ["fpclassify_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) @@ -114,7 +114,7 @@ libc_test( libc_test( name = "isfinite_c_test", srcs = ["isfinite_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) @@ -160,7 +160,7 @@ libc_test( libc_test( name = "isinf_c_test", srcs = ["isinf_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) @@ -206,7 +206,7 @@ libc_test( libc_test( name = "isnan_c_test", srcs = ["isnan_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) @@ -252,14 +252,14 @@ libc_test( libc_test( name = "isnormal_c_test", srcs = ["isnormal_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) libc_test( name = "issubnormal_c_test", srcs = ["issubnormal_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) @@ -305,7 +305,7 @@ libc_test( libc_test( name = "iszero_c_test", srcs = ["iszero_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) @@ -361,7 +361,7 @@ libc_test( libc_test( name = "signbit_c_test", srcs = ["signbit_test.c"], - use_test_framework = False, + c_test = True, deps = ["//libc:public_headers_deps"], ) diff --git a/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl b/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl index dfe6ff5850704..9aa3073517ac2 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl +++ b/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl @@ -30,7 +30,7 @@ def libc_test( copts = [], deps = [], local_defines = [], - use_test_framework = True, + c_test = False, full_build = False, **kwargs): """Add target for a libc test. @@ -40,7 +40,7 @@ def libc_test( copts: The list of options to add to the C++ compilation command. deps: The list of libc functions and libraries to be linked in. local_defines: The list of target local_defines if any. - use_test_framework: Whether to use the libc unit test `main` function. + c_test: Whether this test is a C unit test (uses LibcCTest). full_build: Whether to compile with LIBC_FULL_BUILD and disallow use of system headers. This is useful for tests that include both LLVM libc headers and proxy headers to avoid conflicting definitions. @@ -56,7 +56,9 @@ def libc_test( "//libc:func_malloc", "//libc:func_realloc", ] - if use_test_framework: + if c_test: + deps = deps + ["//libc/test/UnitTest:LibcCTest"] + else: deps = deps + ["//libc/test/UnitTest:LibcUnitTest"] if full_build: