Files
pybind11/tests/test_cross_module_rtti/CMakeLists.txt
Ralf W. Grosse-Kunstleve 78381e5e28 Improve C++ test infrastructure: progress reporter, timeouts, and skip hanging Move Subinterpreter test (#5942)
* Improve C++ test infrastructure and disable hanging test

This commit improves the C++ test infrastructure to ensure test output
is visible in CI logs, and disables a test that hangs on free-threaded
Python 3.14+.

Changes:

## CI/test infrastructure improvements

- .github/workflows: Added `timeout-minutes: 3` to all C++ test steps
  to prevent indefinite hangs.

- tests/**/CMakeLists.txt: Added `USES_TERMINAL` to C++ test targets
  (cpptest, test_cross_module_rtti, test_pure_cpp) to ensure output is
  shown immediately rather than buffered and possibly lost on crash/timeout.

- tests/test_with_catch/catch.cpp: Added a custom Catch2 progress reporter
  with timestamps, Python version info, and a SIGTERM handler to make test
  execution and failures clearly visible in CI logs.

## Disabled hanging test

- The "Move Subinterpreter" test is disabled on free-threaded Python 3.14+
  due to a hang in Py_EndInterpreter() when the subinterpreter is destroyed
  from a different thread than it was created on. Work on fixing the
  underlying issue will continue under PR #5940.

Context: We were in the dark for months (since we started testing with
Python 3.14t) because CI logs gave no clue about the root cause of hangs.
This led to ignoring intermittent hangs (mostly on macOS). Our hand was
forced only with the Python 3.14.1 release, when hangs became predictable
on all platforms.

For the full development history of these changes, see PR #5933.

* Add test summary to progress reporter

Print the total number of test cases and assertions at the end of the
test run, making it easy to spot if tests are disabled or added.

Example output:
  [  PASSED  ] 20 test cases, 1589 assertions.

* Add PYBIND11_CATCH2_SKIP_IF macro to skip tests at runtime

Catch2 v2 doesn't have native skip support (v3 does with SKIP()).
This macro allows tests to be skipped with a visible message while
still appearing in the test list.

Use this for the Move Subinterpreter test on free-threaded Python 3.14+
so it shows as skipped rather than being conditionally compiled out.

Example output:
  [ RUN      ] Move Subinterpreter
  [ SKIPPED ] Skipped on free-threaded Python 3.14+ (see PR #5940)
  [       OK ] Move Subinterpreter

* Fix clang-tidy bugprone-macro-parentheses warning in PYBIND11_CATCH2_SKIP_IF
2025-12-21 21:25:06 -08:00

71 lines
2.9 KiB
CMake

possibly_uninitialized(PYTHON_MODULE_EXTENSION Python_INTERPRETER_ID)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy"
OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
OR "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy")
message(STATUS "Skipping visibility test on PyPy or GraalPy")
add_custom_target(test_cross_module_rtti
)# Dummy target on PyPy or GraalPy. Embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return()
endif()
if(TARGET Python::Module AND NOT TARGET Python::Python)
message(STATUS "Skipping visibility test since no embed libs found")
add_custom_target(test_cross_module_rtti) # Dummy target since embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return()
endif()
find_package(Catch 2.13.10)
if(CATCH_FOUND)
message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}")
else()
message(STATUS "Catch not detected. Interpreter tests will be skipped. Install Catch headers"
" manually or use `cmake -DDOWNLOAD_CATCH=ON` to fetch them automatically.")
return()
endif()
include(GenerateExportHeader)
add_library(test_cross_module_rtti_lib SHARED lib.h lib.cpp)
add_library(test_cross_module_rtti_lib::test_cross_module_rtti_lib ALIAS
test_cross_module_rtti_lib)
target_include_directories(test_cross_module_rtti_lib PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(test_cross_module_rtti_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_features(test_cross_module_rtti_lib PUBLIC cxx_std_11)
generate_export_header(test_cross_module_rtti_lib)
pybind11_add_module(test_cross_module_rtti_bindings SHARED bindings.cpp)
target_link_libraries(test_cross_module_rtti_bindings
PUBLIC test_cross_module_rtti_lib::test_cross_module_rtti_lib)
add_executable(test_cross_module_rtti_main catch.cpp test_cross_module_rtti.cpp)
target_link_libraries(
test_cross_module_rtti_main PUBLIC test_cross_module_rtti_lib::test_cross_module_rtti_lib
pybind11::embed Catch2::Catch2)
# Ensure that we have built the python bindings since we load them in main
add_dependencies(test_cross_module_rtti_main test_cross_module_rtti_bindings)
pybind11_enable_warnings(test_cross_module_rtti_main)
pybind11_enable_warnings(test_cross_module_rtti_bindings)
pybind11_enable_warnings(test_cross_module_rtti_lib)
add_custom_target(
test_cross_module_rtti
COMMAND "$<TARGET_FILE:test_cross_module_rtti_main>"
DEPENDS test_cross_module_rtti_main
WORKING_DIRECTORY "$<TARGET_FILE_DIR:test_cross_module_rtti_main>"
USES_TERMINAL # Ensures output is shown immediately (not buffered and possibly lost on crash)
)
set_target_properties(test_cross_module_rtti_bindings PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}")
add_dependencies(check test_cross_module_rtti)