[libc-commits] [libc] 1e8960c - [libc] Add rule named `add_libc_hermetic_test` which adds a hermetic test.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Mon Apr 24 15:44:28 PDT 2023
Author: Siva Chandra Reddy
Date: 2023-04-24T22:43:59Z
New Revision: 1e8960c7a588c117bf703221ce656aeb034219c5
URL: https://github.com/llvm/llvm-project/commit/1e8960c7a588c117bf703221ce656aeb034219c5
DIFF: https://github.com/llvm/llvm-project/commit/1e8960c7a588c117bf703221ce656aeb034219c5.diff
LOG: [libc] Add rule named `add_libc_hermetic_test` which adds a hermetic test.
A convenience wrapper name `add_libc_test` is also added which adds both
a unit test and a hermetic test. The ctype tests have been switched over
to use add_libc_test.
Reviewed By: jhuber6
Differential Revision: https://reviews.llvm.org/D148756
Added:
libc/test/UnitTest/HermeticTestUtils.cpp
libc/test/UnitTest/LibcDeathTestExecutors.cpp
Modified:
libc/CMakeLists.txt
libc/cmake/modules/LLVMLibCTestRules.cmake
libc/test/CMakeLists.txt
libc/test/UnitTest/CMakeLists.txt
libc/test/UnitTest/LibcTest.cpp
libc/test/UnitTest/LibcTest.h
libc/test/UnitTest/LibcTestMain.cpp
libc/test/src/ctype/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 958de3b30ad20..da669a1d5e58e 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -75,11 +75,15 @@ option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" OFF)
option(LIBC_GPU_BUILD "Build libc for the GPU. All CPU build options will be ignored." OFF)
set(LIBC_TARGET_TRIPLE "" CACHE STRING "The target triple for the libc build.")
+set(LIBC_ENABLE_UNITTESTS ON)
+set(LIBC_ENABLE_HERMETIC_TESTS ON)
+
# Defines LIBC_TARGET_ARCHITECTURE and associated macros.
include(LLVMLibCArchitectures)
if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
include(prepare_libc_gpu_build)
+ set(LIBC_ENABLE_UNITTESTS OFF)
endif()
include(LLVMLibCCheckMPFR)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index c7689749b84d2..a059ac2134acb 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -77,7 +77,7 @@ function(create_libc_unittest fq_target_name)
cmake_parse_arguments(
"LIBC_UNITTEST"
- "NO_RUN_POSTBUILD;NO_LIBC_UNITTEST_TEST_MAIN" # Optional arguments
+ "NO_RUN_POSTBUILD" # Optional arguments
"SUITE;CXX_STANDARD" # Single value arguments
"SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_LIBRARIES;FLAGS" # Multi-value arguments
${ARGN}
@@ -179,11 +179,7 @@ function(create_libc_unittest fq_target_name)
)
# LibcUnitTest should not depend on anything in LINK_LIBRARIES.
- if(NO_LIBC_UNITTEST_TEST_MAIN)
- list(APPEND link_libraries LibcUnitTest)
- else()
- list(APPEND link_libraries LibcUnitTest LibcUnitTestMain)
- endif()
+ list(APPEND link_libraries LibcTestMain LibcUnitTest)
target_link_libraries(${fq_build_target_name} PRIVATE ${link_libraries})
@@ -386,6 +382,8 @@ function(add_libc_fuzzer target_name)
endfunction(add_libc_fuzzer)
+# DEPRECATED: Use add_hermetic_test instead.
+#
# Rule to add an integration test. An integration test is like a unit test
# but does not use the system libc. Not even the startup objects from the
# system libc are linked in to the final executable. The final exe is fully
@@ -544,3 +542,158 @@ function(add_integration_test test_name)
)
add_dependencies(${INTEGRATION_TEST_SUITE} ${fq_target_name})
endfunction(add_integration_test)
+
+set(LIBC_HERMETIC_TEST_COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_DEFAULT}
+ -fpie -ffreestanding -fno-exceptions -fno-rtti)
+# The GPU build requires overriding the default CMake triple and architecture.
+if(LIBC_GPU_TARGET_ARCHITECTURE_IS_AMDGPU)
+ list(APPEND LIBC_HERMETIC_TEST_COMPILE_OPTIONS
+ -mcpu=${LIBC_GPU_TARGET_ARCHITECTURE} -flto --target=${LIBC_GPU_TARGET_TRIPLE})
+elseif(LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
+ get_nvptx_compile_options(nvptx_options ${LIBC_GPU_TARGET_ARCHITECTURE})
+ list(APPEND ${nvptx_options} --target=${LIBC_GPU_TARGET_TRIPLE})
+endif()
+
+# Rule to add a hermetic test. A hermetic test is one whose executable is fully
+# statically linked and consists of pieces drawn only from LLVM's libc. Nothing,
+# including the startup objects, come from the system libc.
+#
+# Usage:
+# add_libc_hermetic_test(
+# <target name>
+# SUITE <the suite to which the test should belong>
+# SRCS <src1.cpp> [src2.cpp ...]
+# HDRS [hdr1.cpp ...]
+# DEPENDS <list of entrypoint or other object targets>
+# ARGS <list of command line arguments to be passed to the test>
+# ENV <list of environment variables to set before running the test>
+# COMPILE_OPTIONS <list of special compile options for the test>
+# LOADER_ARGS <list of special args to loaders (like the GPU loader)>
+# )
+function(add_libc_hermetic_test test_name)
+ if(NOT TARGET libc.startup.${LIBC_TARGET_OS}.crt1)
+ message(VERBOSE "Skipping ${fq_target_name} as it is not available on ${LIBC_TARGET_OS}.")
+ return()
+ endif()
+ cmake_parse_arguments(
+ "HERMETIC_TEST"
+ "" # No optional arguments
+ "SUITE" # Single value arguments
+ "SRCS;HDRS;DEPENDS;ARGS;ENV;COMPILE_OPTIONS;LOADER_ARGS" # Multi-value arguments
+ ${ARGN}
+ )
+
+ if(NOT HERMETIC_TEST_SUITE)
+ message(FATAL_ERROR "SUITE not specified for ${fq_target_name}")
+ endif()
+ if(NOT HERMETIC_TEST_SRCS)
+ message(FATAL_ERROR "The SRCS list for add_integration_test is missing.")
+ endif()
+
+ get_fq_target_name(${test_name} fq_target_name)
+ get_fq_target_name(${test_name}.libc fq_libc_target_name)
+
+ get_fq_deps_list(fq_deps_list ${HERMETIC_TEST_DEPENDS})
+ list(APPEND fq_deps_list
+ # Hermetic tests use the platform's startup object. So, their deps also
+ # have to be collected.
+ libc.startup.${LIBC_TARGET_OS}.crt1
+ # We always add the memory functions objects. This is because the
+ # compiler's codegen can emit calls to the C memory functions.
+ libc.src.string.bcmp
+ libc.src.string.bzero
+ libc.src.string.memcmp
+ libc.src.string.memcpy
+ libc.src.string.memmove
+ libc.src.string.memset
+ )
+ list(REMOVE_DUPLICATES fq_deps_list)
+
+ # TODO: Instead of gathering internal object files from entrypoints,
+ # collect the object files with public names of entrypoints.
+ get_object_files_for_test(
+ link_object_files skipped_entrypoints_list ${fq_deps_list})
+ if(skipped_entrypoints_list)
+ set(msg "Skipping unittest ${fq_target_name} as it has missing deps: "
+ "${skipped_entrypoints_list}.")
+ message(STATUS ${msg})
+ return()
+ endif()
+ list(REMOVE_DUPLICATES link_object_files)
+
+ # Make a library of all deps
+ add_library(
+ ${fq_target_name}.__libc__
+ STATIC
+ EXCLUDE_FROM_ALL
+ ${link_object_files}
+ )
+ set_target_properties(${fq_target_name}.__libc__
+ PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ set_target_properties(${fq_target_name}.__libc__
+ PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc)
+
+ set(fq_build_target_name ${fq_target_name}.__build__)
+ add_executable(
+ ${fq_build_target_name}
+ EXCLUDE_FROM_ALL
+ # The NVIDIA 'nvlink' linker does not currently support static libraries.
+ $<$<BOOL:${LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX}>:${link_object_files}>
+ ${HERMETIC_TEST_SRCS}
+ ${HERMETIC_TEST_HDRS}
+ )
+ set_target_properties(${fq_build_target_name}
+ PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ #OUTPUT_NAME ${fq_target_name}
+ )
+ target_include_directories(
+ ${fq_build_target_name}
+ PRIVATE
+ ${LIBC_SOURCE_DIR}
+ ${LIBC_BUILD_DIR}
+ ${LIBC_BUILD_DIR}/include
+ )
+ target_compile_options(${fq_build_target_name}
+ PRIVATE ${LIBC_HERMETIC_TEST_COMPILE_OPTIONS} ${HERMETIC_TEST_COMPILE_OPTIONS})
+
+ target_link_options(${fq_build_target_name} PRIVATE -nostdlib -static)
+ target_link_libraries(
+ ${fq_build_target_name}
+ libc.startup.${LIBC_TARGET_OS}.crt1
+ LibcTestMain LibcHermeticTest
+ # The NVIDIA 'nvlink' linker does not currently support static libraries.
+ $<$<NOT:$<BOOL:${LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX}>>:${fq_target_name}.__libc__>)
+ add_dependencies(${fq_build_target_name}
+ LibcHermeticTest
+ ${HERMETIC_TEST_DEPENDS})
+
+ # Tests on the GPU require an external loader utility to launch the kernel.
+ if(TARGET libc.utils.gpu.loader)
+ add_dependencies(${fq_build_target_name} libc.utils.gpu.loader)
+ get_target_property(gpu_loader_exe libc.utils.gpu.loader "EXECUTABLE")
+ endif()
+
+ set(test_cmd ${HERMETIC_TEST_ENV}
+ $<$<BOOL:${LIBC_TARGET_ARCHITECTURE_IS_GPU}>:${gpu_loader_exe}> ${HERMETIC_TEST_LOADER_ARGS}
+ $<TARGET_FILE:${fq_build_target_name}> ${HERMETIC_TEST_ARGS})
+ add_custom_target(
+ ${fq_target_name}
+ COMMAND ${test_cmd}
+ COMMAND_EXPAND_LISTS
+ COMMENT "Running hermetic test ${fq_target_name}"
+ )
+
+ add_dependencies(${HERMETIC_TEST_SUITE} ${fq_target_name})
+ add_dependencies(libc-hermetic-tests ${fq_target_name})
+endfunction(add_libc_hermetic_test)
+
+# A convenience function to add both a unit test as well as a hermetic test.
+function(add_libc_test test_name)
+ if(LIBC_ENABLE_UNITTESTS)
+ add_libc_unittest(${test_name}.__unit__ ${ARGN})
+ endif()
+ if(LIBC_ENABLE_HERMETIC_TESTS)
+ add_libc_hermetic_test(${test_name}.__hermetic__ ${ARGN})
+ endif()
+endfunction(add_libc_test)
diff --git a/libc/test/CMakeLists.txt b/libc/test/CMakeLists.txt
index 710f1138a6f2b..333873a07b22a 100644
--- a/libc/test/CMakeLists.txt
+++ b/libc/test/CMakeLists.txt
@@ -1,6 +1,7 @@
add_custom_target(check-libc)
add_custom_target(libc-unit-tests)
-add_dependencies(check-libc libc-unit-tests)
+add_custom_target(libc-hermetic-tests)
+add_dependencies(check-libc libc-unit-tests libc-hermetic-tests)
add_custom_target(exhaustive-check-libc)
add_custom_target(libc-long-running-tests)
diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt
index f3d5a2b191943..389a59c4401a2 100644
--- a/libc/test/UnitTest/CMakeLists.txt
+++ b/libc/test/UnitTest/CMakeLists.txt
@@ -1,5 +1,4 @@
-set(libc_unit_test_srcs
- ExecuteFunction.h
+set(libc_test_srcs_common
Test.h
LibcTest.cpp
LibcTest.h
@@ -7,32 +6,47 @@ set(libc_unit_test_srcs
TestLogger.h
)
+set(libc_death_test_srcs ExecuteFunction.h)
if(${LIBC_TARGET_OS} STREQUAL "linux")
- list(APPEND libc_unit_test_srcs ExecuteFunctionUnix.cpp)
+ list(APPEND libc_death_test_srcs
+ LibcDeathTestExecutors.cpp ExecuteFunctionUnix.cpp)
endif()
add_library(
LibcUnitTest
- ${libc_unit_test_srcs}
+ ${libc_test_srcs_common}
+ ${libc_death_test_srcs}
)
-target_include_directories(LibcUnitTest PUBLIC ${LIBC_SOURCE_DIR})
-add_dependencies(
- LibcUnitTest
- libc.src.__support.CPP.string
- libc.src.__support.CPP.string_view
- libc.src.__support.CPP.type_traits
- libc.src.__support.OSUtil.osutil
- libc.src.__support.uint128)
+add_library(
+ LibcHermeticTest
+ ${libc_test_srcs_common}
+ HermeticTestUtils.cpp
+)
+
+foreach(lib LibcUnitTest LibcHermeticTest)
+ target_include_directories(${lib} PUBLIC ${LIBC_SOURCE_DIR})
+ target_compile_options(${lib} PRIVATE ${LIBC_HERMETIC_TEST_COMPILE_OPTIONS}
+ -fno-exceptions -fno-rtti)
+ add_dependencies(${lib}
+ libc.src.__support.CPP.string
+ libc.src.__support.CPP.string_view
+ libc.src.__support.CPP.type_traits
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.uint128
+ )
+endforeach()
+
+target_compile_options(LibcHermeticTest PRIVATE -ffreestanding -nostdlib -nostdlib++)
add_library(
- LibcUnitTestMain
+ LibcTestMain
LibcTestMain.cpp
)
-target_include_directories(LibcUnitTestMain PUBLIC ${LIBC_SOURCE_DIR})
-add_dependencies(LibcUnitTestMain LibcUnitTest)
-target_link_libraries(LibcUnitTestMain PUBLIC LibcUnitTest)
+target_include_directories(LibcTestMain PUBLIC ${LIBC_SOURCE_DIR})
+target_compile_options(LibcTestMain PRIVATE -fno-exceptions -fno-rtti)
+add_dependencies(LibcTestMain LibcUnitTest)
add_header_library(
string_utils
diff --git a/libc/test/UnitTest/HermeticTestUtils.cpp b/libc/test/UnitTest/HermeticTestUtils.cpp
new file mode 100644
index 0000000000000..ea819c4174371
--- /dev/null
+++ b/libc/test/UnitTest/HermeticTestUtils.cpp
@@ -0,0 +1,91 @@
+//===-- Implementation of libc death test executors -----------------------===//
+//
+// 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 <stddef.h>
+#include <stdint.h>
+
+namespace __llvm_libc {
+
+int bcmp(const void *lhs, const void *rhs, size_t count);
+void bzero(void *ptr, size_t count);
+int memcmp(const void *lhs, const void *rhs, size_t count);
+void *memcpy(void *__restrict, const void *__restrict, size_t);
+void *memmove(void *dst, const void *src, size_t count);
+void *memset(void *ptr, int value, size_t count);
+
+} // namespace __llvm_libc
+
+namespace {
+
+// Integration tests cannot use the SCUDO standalone allocator as SCUDO pulls
+// various other parts of the libc. Since SCUDO development does not use
+// LLVM libc build rules, it is very hard to keep track or pull all that SCUDO
+// requires. Hence, as a work around for this problem, we use a simple allocator
+// which just hands out continuous blocks from a statically allocated chunk of
+// memory.
+static uint8_t memory[16384];
+static uint8_t *ptr = memory;
+
+} // anonymous namespace
+
+extern "C" {
+
+// Hermetic tests rely on the following memory functions. This is because the
+// compiler code generation can emit calls to them. We want to map the external
+// entrypoint to the internal implementation of the function used for testing.
+// This is done manually as not all targets support aliases.
+
+int bcmp(const void *lhs, const void *rhs, size_t count) {
+ return __llvm_libc::bcmp(lhs, rhs, count);
+}
+void bzero(void *ptr, size_t count) { __llvm_libc::bzero(ptr, count); }
+int memcmp(const void *lhs, const void *rhs, size_t count) {
+ return __llvm_libc::memcmp(lhs, rhs, count);
+}
+void *memcpy(void *__restrict dst, const void *__restrict src, size_t count) {
+ return __llvm_libc::memcpy(dst, src, count);
+}
+void *memmove(void *dst, const void *src, size_t count) {
+ return __llvm_libc::memmove(dst, src, count);
+}
+void *memset(void *ptr, int value, size_t count) {
+ return __llvm_libc::memset(ptr, value, count);
+}
+
+void *malloc(size_t s) {
+ void *mem = ptr;
+ ptr += s;
+ return mem;
+}
+
+void free(void *) {}
+
+void *realloc(void *ptr, size_t s) {
+ free(ptr);
+ return malloc(s);
+}
+
+// The unit test framework uses pure virtual functions. Since hermetic tests
+// cannot depend C++ runtime libraries, implement dummy functions to support
+// the virtual function runtime.
+void __cxa_pure_virtual() {
+ // A pure virtual being called is an error so we just trap.
+ __builtin_trap();
+}
+
+// Integration tests are linked with -nostdlib. BFD linker expects
+// __dso_handle when -nostdlib is used.
+void *__dso_handle = nullptr;
+
+} // extern "C"
+
+void operator delete(void *) {
+ // The libc runtime should not use the global delete operator. Hence,
+ // we just trap here to catch any such accidental usages.
+ __builtin_trap();
+}
diff --git a/libc/test/UnitTest/LibcDeathTestExecutors.cpp b/libc/test/UnitTest/LibcDeathTestExecutors.cpp
new file mode 100644
index 0000000000000..c756a8dbe0302
--- /dev/null
+++ b/libc/test/UnitTest/LibcDeathTestExecutors.cpp
@@ -0,0 +1,102 @@
+//===-- Implementation of libc death test executors -----------------------===//
+//
+// 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 "LibcTest.h"
+
+#include "test/UnitTest/ExecuteFunction.h"
+#include "test/UnitTest/TestLogger.h"
+
+#include <cassert>
+
+namespace __llvm_libc {
+namespace testing {
+
+bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal,
+ const char *LHSStr, const char *RHSStr,
+ const char *File, unsigned long Line) {
+ 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';
+ return false;
+ }
+
+ if (Result.timed_out()) {
+ Ctx->markFail();
+ tlog << File << ":" << Line << ": FAILURE\n"
+ << "Process timed out after " << 500 << " milliseconds.\n";
+ return false;
+ }
+
+ if (Result.exited_normally()) {
+ Ctx->markFail();
+ tlog << File << ":" << Line << ": FAILURE\n"
+ << "Expected " << LHSStr
+ << " to be killed by a signal\nBut it exited normally!\n";
+ return false;
+ }
+
+ int KilledBy = Result.get_fatal_signal();
+ assert(KilledBy != 0 && "Not killed by any signal");
+ if (Signal == -1 || KilledBy == Signal)
+ return true;
+
+ using testutils::signal_as_string;
+ Ctx->markFail();
+ tlog << File << ":" << Line << ": FAILURE\n"
+ << " Expected: " << LHSStr << '\n'
+ << "To be killed by signal: " << Signal << '\n'
+ << " Which is: " << signal_as_string(Signal) << '\n'
+ << " But it was killed by: " << KilledBy << '\n'
+ << " Which is: " << signal_as_string(KilledBy) << '\n';
+ return false;
+}
+
+bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode,
+ const char *LHSStr, const char *RHSStr,
+ const char *File, unsigned long Line) {
+ 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';
+ return false;
+ }
+
+ if (Result.timed_out()) {
+ Ctx->markFail();
+ tlog << File << ":" << Line << ": FAILURE\n"
+ << "Process timed out after " << 500 << " milliseconds.\n";
+ return false;
+ }
+
+ if (!Result.exited_normally()) {
+ Ctx->markFail();
+ tlog << File << ":" << Line << ": FAILURE\n"
+ << "Expected " << LHSStr << '\n'
+ << "to exit with exit code " << ExitCode << '\n'
+ << "But it exited abnormally!\n";
+ return false;
+ }
+
+ int ActualExit = Result.get_exit_code();
+ if (ActualExit == ExitCode)
+ return true;
+
+ Ctx->markFail();
+ tlog << File << ":" << Line << ": FAILURE\n"
+ << "Expected exit code of: " << LHSStr << '\n'
+ << " Which is: " << ActualExit << '\n'
+ << " To be equal to: " << RHSStr << '\n'
+ << " Which is: " << ExitCode << '\n';
+ return false;
+}
+
+} // namespace testing
+} // namespace __llvm_libc
diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp
index b3a7fc18dfda2..dabfe2b6bd8a0 100644
--- a/libc/test/UnitTest/LibcTest.cpp
+++ b/libc/test/UnitTest/LibcTest.cpp
@@ -11,28 +11,11 @@
#include "src/__support/CPP/string.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/UInt128.h"
-#include "test/UnitTest/ExecuteFunction.h"
#include "test/UnitTest/TestLogger.h"
-#include <cassert>
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 {
// When the value is UInt128 or __uint128_t, show its hexadecimal digits.
@@ -149,6 +132,12 @@ bool test(RunContext *Ctx, TestCondition Cond, ValType LHS, ValType RHS,
Test *Test::Start = nullptr;
Test *Test::End = nullptr;
+int argc = 0;
+char **argv = nullptr;
+char **envp = nullptr;
+
+using internal::RunContext;
+
void Test::addTest(Test *T) {
if (End == nullptr) {
Start = T;
@@ -326,90 +315,5 @@ bool Test::testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr,
return false;
}
-#ifdef ENABLE_SUBPROCESS_TESTS
-
-bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal,
- const char *LHSStr, const char *RHSStr,
- const char *File, unsigned long Line) {
- 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';
- return false;
- }
-
- if (Result.timed_out()) {
- Ctx->markFail();
- tlog << File << ":" << Line << ": FAILURE\n"
- << "Process timed out after " << 500 << " milliseconds.\n";
- return false;
- }
-
- if (Result.exited_normally()) {
- Ctx->markFail();
- tlog << File << ":" << Line << ": FAILURE\n"
- << "Expected " << LHSStr
- << " to be killed by a signal\nBut it exited normally!\n";
- return false;
- }
-
- int KilledBy = Result.get_fatal_signal();
- assert(KilledBy != 0 && "Not killed by any signal");
- if (Signal == -1 || KilledBy == Signal)
- return true;
-
- using testutils::signal_as_string;
- Ctx->markFail();
- tlog << File << ":" << Line << ": FAILURE\n"
- << " Expected: " << LHSStr << '\n'
- << "To be killed by signal: " << Signal << '\n'
- << " Which is: " << signal_as_string(Signal) << '\n'
- << " But it was killed by: " << KilledBy << '\n'
- << " Which is: " << signal_as_string(KilledBy) << '\n';
- return false;
-}
-
-bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode,
- const char *LHSStr, const char *RHSStr,
- const char *File, unsigned long Line) {
- 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';
- return false;
- }
-
- if (Result.timed_out()) {
- Ctx->markFail();
- tlog << File << ":" << Line << ": FAILURE\n"
- << "Process timed out after " << 500 << " milliseconds.\n";
- return false;
- }
-
- if (!Result.exited_normally()) {
- Ctx->markFail();
- tlog << File << ":" << Line << ": FAILURE\n"
- << "Expected " << LHSStr << '\n'
- << "to exit with exit code " << ExitCode << '\n'
- << "But it exited abnormally!\n";
- return false;
- }
-
- int ActualExit = Result.get_exit_code();
- if (ActualExit == ExitCode)
- return true;
-
- Ctx->markFail();
- tlog << File << ":" << Line << ": FAILURE\n"
- << "Expected exit code of: " << LHSStr << '\n'
- << " Which is: " << ActualExit << '\n'
- << " To be equal to: " << RHSStr << '\n'
- << " Which is: " << ExitCode << '\n';
- return false;
-}
-
-#endif // ENABLE_SUBPROCESS_TESTS
} // namespace testing
} // namespace __llvm_libc
diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h
index a1343e2520f78..73683770f2d46 100644
--- a/libc/test/UnitTest/LibcTest.h
+++ b/libc/test/UnitTest/LibcTest.h
@@ -23,8 +23,6 @@
namespace __llvm_libc {
namespace testing {
-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 boolean values, but use integral return values to indicate true or
@@ -42,6 +40,18 @@ enum TestCondition {
namespace internal {
+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;
+};
+
template <typename ValType>
bool test(RunContext *Ctx, TestCondition Cond, ValType LHS, ValType RHS,
const char *LHSStr, const char *RHSStr, const char *File,
@@ -65,9 +75,9 @@ template <typename T> struct Matcher : public MatcherBase {
class Test {
private:
Test *Next = nullptr;
- RunContext *Ctx = nullptr;
+ internal::RunContext *Ctx = nullptr;
- void setContext(RunContext *C) { Ctx = C; }
+ void setContext(internal::RunContext *C) { Ctx = C; }
public:
virtual ~Test() {}
@@ -161,6 +171,10 @@ class Test {
static Test *End;
};
+extern int argc;
+extern char **argv;
+extern char **envp;
+
namespace internal {
constexpr bool same_prefix(char const *lhs, char const *rhs, int const len) {
diff --git a/libc/test/UnitTest/LibcTestMain.cpp b/libc/test/UnitTest/LibcTestMain.cpp
index 46e19dd027365..756d1196bc365 100644
--- a/libc/test/UnitTest/LibcTestMain.cpp
+++ b/libc/test/UnitTest/LibcTestMain.cpp
@@ -12,7 +12,11 @@ static const char *getTestFilter(int argc, char *argv[]) {
return argc > 1 ? argv[1] : nullptr;
}
-int main(int argc, char *argv[]) {
+extern "C" int main(int argc, char **argv, char **envp) {
+ __llvm_libc::testing::argc = argc;
+ __llvm_libc::testing::argv = argv;
+ __llvm_libc::testing::envp = envp;
+
const char *TestFilter = getTestFilter(argc, argv);
return __llvm_libc::testing::Test::runTests(TestFilter);
}
diff --git a/libc/test/src/ctype/CMakeLists.txt b/libc/test/src/ctype/CMakeLists.txt
index 34377aefc0ecd..0621f83c2bae7 100644
--- a/libc/test/src/ctype/CMakeLists.txt
+++ b/libc/test/src/ctype/CMakeLists.txt
@@ -1,159 +1,159 @@
-add_custom_target(libc_ctype_unittests)
+add_custom_target(libc-ctype-tests)
-add_libc_unittest(
+add_libc_test(
isalnum_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isalnum_test.cpp
DEPENDS
libc.src.ctype.isalnum
)
-add_libc_unittest(
+add_libc_test(
isalpha_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isalpha_test.cpp
DEPENDS
libc.src.ctype.isalpha
)
-add_libc_unittest(
+add_libc_test(
isascii_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isascii_test.cpp
DEPENDS
libc.src.ctype.isascii
)
-add_libc_unittest(
+add_libc_test(
isblank_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isblank_test.cpp
DEPENDS
libc.src.ctype.isblank
)
-add_libc_unittest(
+add_libc_test(
iscntrl_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
iscntrl_test.cpp
DEPENDS
libc.src.ctype.iscntrl
)
-add_libc_unittest(
+add_libc_test(
isdigit_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isdigit_test.cpp
DEPENDS
libc.src.ctype.isdigit
)
-add_libc_unittest(
+add_libc_test(
isgraph_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isgraph_test.cpp
DEPENDS
libc.src.ctype.isgraph
)
-add_libc_unittest(
+add_libc_test(
islower_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
islower_test.cpp
DEPENDS
libc.src.ctype.islower
)
-add_libc_unittest(
+add_libc_test(
isprint_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isprint_test.cpp
DEPENDS
libc.src.ctype.isprint
)
-add_libc_unittest(
+add_libc_test(
ispunct_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
ispunct_test.cpp
DEPENDS
libc.src.ctype.ispunct
)
-add_libc_unittest(
+add_libc_test(
isspace_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isspace_test.cpp
DEPENDS
libc.src.ctype.isspace
)
-add_libc_unittest(
+add_libc_test(
isupper_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isupper_test.cpp
DEPENDS
libc.src.ctype.isupper
)
-add_libc_unittest(
+add_libc_test(
isxdigit_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
isxdigit_test.cpp
DEPENDS
libc.src.ctype.isxdigit
)
-add_libc_unittest(
+add_libc_test(
toascii_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
toascii_test.cpp
DEPENDS
libc.src.ctype.toascii
)
-add_libc_unittest(
+add_libc_test(
tolower_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
tolower_test.cpp
DEPENDS
libc.src.ctype.tolower
)
-add_libc_unittest(
+add_libc_test(
toupper_test
SUITE
- libc_ctype_unittests
+ libc-ctype-tests
SRCS
toupper_test.cpp
DEPENDS
More information about the libc-commits
mailing list