diff --git a/CMakeLists.txt b/CMakeLists.txt index e9fcbdb77d..c4f013f599 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1190,6 +1190,18 @@ if(WITH_TESTS OR WITH_BENCHMARK_TOOLS) endif() if(WITH_TESTS) + # c_test - doesn't use gtest + # env_test - suspicious use of test::TmpDir + # deletefile_test - serial because it generates giant temporary files in + # its various tests. Running its tests in parallel can fill up your /dev/shm + # db_bloom_filter_test - serial because excessive space usage by instances + # of DBFilterConstructionReserveMemoryTestWithParam can fill up /dev/shm + set(NON_PARALLEL_TEST + c_test + env_test + deletefile_test + db_bloom_filter_test + ) set(TESTS db/db_basic_test.cc env/env_basic_test.cc @@ -1396,7 +1408,10 @@ if(WITH_TESTS) utilities/cassandra/test_utils.cc ) enable_testing() - add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) + add_custom_target(check + COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/CTestRunner.cmake + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + VERBATIM USES_TERMINAL) set(TESTUTILLIB testutillib${ARTIFACT_SUFFIX}) add_library(${TESTUTILLIB} STATIC ${TESTUTIL_SOURCE}) target_link_libraries(${TESTUTILLIB} ${ROCKSDB_LIB}) @@ -1419,10 +1434,12 @@ if(WITH_TESTS) OUTPUT_NAME ${exename}${ARTIFACT_SUFFIX} ) target_link_libraries(${exename}${ARTIFACT_SUFFIX} ${TESTUTILLIB} testharness gtest ${THIRDPARTY_LIBS} ${ROCKSDB_LIB}) - if(NOT "${exename}" MATCHES "db_sanity_test") + if(NOT "${exename}" IN_LIST NON_PARALLEL_TEST) gtest_discover_tests(${exename} DISCOVERY_TIMEOUT 120) - add_dependencies(check ${exename}${ARTIFACT_SUFFIX}) + else() + add_test(NAME ${exename} COMMAND ${exename}${ARTIFACT_SUFFIX}) endif() + add_dependencies(check ${exename}${ARTIFACT_SUFFIX}) endforeach(sourcefile ${TESTS}) if(WIN32) diff --git a/cmake/CTestRunner.cmake b/cmake/CTestRunner.cmake new file mode 100644 index 0000000000..ca8a2f85ab --- /dev/null +++ b/cmake/CTestRunner.cmake @@ -0,0 +1,85 @@ +# Copyright (C) 2022 Speedb Ltd. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Choose the amount of tests to run in parallel if CTEST_PARALLEL_LEVEL wasn't set +if(NOT DEFINED ENV{CTEST_PARALLEL_LEVEL}) + # Compatibility with the Makefile: support the `J` environment variable + if(DEFINED ENV{J} AND "$ENV{J}" GREATER 0) + set(ENV{CTEST_PARALLEL_LEVEL} ${ENV{J}}) + else() + include(ProcessorCount) + ProcessorCount(NCPU) + if(NOT NCPU EQUAL 0) + set(ENV{CTEST_PARALLEL_LEVEL} ${NCPU}) + endif() + endif() +endif() + +# For Makefile compatibility try the following sequence if TEST_TMPDIR isn't set: +# * Use TMPD if set +# * Create a temp directory under /dev/shm on Linux if it has the sticky bit set +# * Use TMPDIR if set, and if not on Windows create a temp directory under it +# * If not on Windows, fall back to creating a temp directory under /tmp if exists +if(NOT DEFINED ENV{TEST_TMPDIR}) + # Use TMPD if set + if(DEFINED ENV{TMPD}) + set(test_dir ENV{TMPD}) + else() + # On Linux, use /dev/shm if the sticky bit is set + if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux" AND IS_DIRECTORY /dev/shm) + execute_process(COMMAND test -k /dev/shm RESULT_VARIABLE status OUTPUT_QUIET ERROR_QUIET) + if(status EQUAL 0) + set(test_dir /dev/shm) + endif() + endif() + # Use TMPDIR as base if set + if(NOT DEFINED test_dir AND IS_DIRECTORY "$ENV{TMPDIR}") + set(test_dir $ENV{TMPDIR}) + endif() + if(NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") + # Fall back to /tmp if exists + if(NOT DEFINED test_dir AND IS_DIRECTORY /tmp) + set(test_dir /tmp) + endif() + # Create a temporary directory under the test location that we determined + if(DEFINED test_dir) + execute_process( + COMMAND "mktemp" "-d" "${test_dir}/rocksdb.XXXX" + RESULT_VARIABLE status OUTPUT_VARIABLE tmpdir + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT status EQUAL 0) + message(FATAL_ERROR "mkdtemp failed") + endif() + set(test_dir ${tmpdir}) + endif() + endif() + endif() + if(DEFINED test_dir) + set(ENV{TEST_TMPDIR} ${test_dir}) + endif() +endif() + +if(DEFINED ENV{TEST_TMPDIR}) + message(STATUS "Running $ENV{CTEST_PARALLEL_LEVEL} tests in parallel in $ENV{TEST_TMPDIR}") +endif() + +# Use a timeout of 10 minutes per test by default +if(DEFINED ENV{TEST_TIMEOUT}) + set(test_timeout "$ENV{TEST_TIMEOUT}") +else() + set(test_timeout 600) +endif() + +# Run all tests, and show test output on failure +execute_process(COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --timeout ${test_timeout})