From 488255d85c1765dc895fad708cb73c25995ee02c Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Tue, 28 Dec 2021 09:26:54 +0100 Subject: [PATCH] simplify creation of CMake files for Python tests (#46642) --- cmake/UsePythonTest.cmake | 142 +++++++++++------------------ cmake_templates/PyQgsTest.cmake.in | 24 +++++ 2 files changed, 78 insertions(+), 88 deletions(-) create mode 100644 cmake_templates/PyQgsTest.cmake.in diff --git a/cmake/UsePythonTest.cmake b/cmake/UsePythonTest.cmake index ee322dde752..c85b777eb8f 100644 --- a/cmake/UsePythonTest.cmake +++ b/cmake/UsePythonTest.cmake @@ -1,10 +1,8 @@ -# Add a python test from a python file # One cannot simply do: -# SET(ENV{PYTHONPATH} ${LIBRARY_OUTPUT_PATH}) -# SET(my_test "from test_mymodule import *\;test_mymodule()") -# ADD_TEST(PYTHON-TEST-MYMODULE python -c ${my_test}) +# Add a python test from a python file +# # Since cmake is only transmitting the ADD_TEST line to ctest thus you are losing # the env var. The only way to store the env var is to physically write in the cmake script -# whatever PYTHONPATH you want and then add the test as 'cmake -P python_test.cmake' +# whatever PYTHONPATH or variable you want and then add the test as 'cmake -P python_test.cmake' # # Usage: # ADD_PYTHON_TEST(PYTHON-TEST test.py) @@ -12,104 +10,72 @@ # Optionally pass environment variables to your test # ADD_PYTHON_TEST(PYTHON-TEST test.py FOO="bar" BAZ="quux") # +# Timeout can be set by doing ADD_PYTHON_TEST(PYTHON-TEST test.py TIMEOUT=10) +# +# # Copyright (c) 2006-2010 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS # -MACRO(ADD_PYTHON_TEST TESTNAME FILENAME) - GET_SOURCE_FILE_PROPERTY(loc ${FILENAME} LOCATION) - GET_SOURCE_FILE_PROPERTY(pyenv ${FILENAME} PYTHONPATH) +macro(ADD_PYTHON_TEST TESTNAME FILENAME) + get_source_file_property(QGIS_PYTEST_FILE_LOC ${FILENAME} LOCATION) + get_source_file_property(QGIS_PYTEST_PYENV ${FILENAME} PYTHONPATH) + #Avoid "NOTFOUND" string when setting LD_LIBRARY_PATH later - if(EXISTS "${pyenv}") - set(pyenv "${pyenv}:") + if(EXISTS "${QGIS_PYTEST_PYENV}") + set(QGIS_PYTEST_PYENV "${QGIS_PYTEST_PYENV}:") else() - set(pyenv "") + set(QGIS_PYTEST_PYENV "") endif() - IF(WIN32) - STRING(REGEX REPLACE ":" " " wo_semicolon "${ARGN}") - IF(USING_NINJA OR USING_NMAKE) - FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " -SET(ENV{QGIS_PREFIX_PATH} \"${QGIS_OUTPUT_DIRECTORY}/bin\") -SET(ENV{PATH} \"${QGIS_OUTPUT_DIRECTORY}/bin;\$ENV{PATH}\") -SET(ENV{PYTHONPATH} \"${PYTHON_OUTPUT_DIRECTORY};${PYTHON_OUTPUT_DIRECTORY}/plugins;${CMAKE_SOURCE_DIR}/tests/src/python;\$ENV{PYTHONPATH}\") -MESSAGE(\"PATH:\$ENV{PATH}\") -") - ELSE(USING_NINJA OR USING_NMAKE) - FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " -SET(ENV{QGIS_PREFIX_PATH} \"${QGIS_OUTPUT_DIRECTORY}/bin/\${CMAKE_BUILD_TYPE}\") -SET(ENV{PATH} \"${QGIS_OUTPUT_DIRECTORY}/bin/\${CMAKE_BUILD_TYPE};\$ENV{PATH}\") -SET(ENV{PYTHONPATH} \"${PYTHON_OUTPUT_DIRECTORY};${PYTHON_OUTPUT_DIRECTORY}/plugins;${CMAKE_SOURCE_DIR}/tests/src/python;\$ENV{PYTHONPATH}\") -MESSAGE(\"PATH:\$ENV{PATH}\") -") - ENDIF(USING_NINJA OR USING_NMAKE) - ELSE(WIN32) - STRING(REGEX REPLACE ";" " " wo_semicolon "${ARGN}") - FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " -SET(ENV{QGIS_PREFIX_PATH} \"${QGIS_OUTPUT_DIRECTORY}\") -SET(ENV{LD_LIBRARY_PATH} \"${pyenv}${QGIS_OUTPUT_DIRECTORY}/lib:\$ENV{LD_LIBRARY_PATH}\") -SET(ENV{PYTHONPATH} \"${PYTHON_OUTPUT_DIRECTORY}:${PYTHON_OUTPUT_DIRECTORY}/plugins:${CMAKE_SOURCE_DIR}/tests/src/python:\$ENV{PYTHONPATH}\") -MESSAGE(\"export LD_LIBRARY_PATH=\$ENV{LD_LIBRARY_PATH}\") -") - ENDIF(WIN32) - SET(TEST_TIMEOUT 0) + set(_QGIS_PYTEST_PYTHONPATHS "${PYTHON_OUTPUT_DIRECTORY}" "${PYTHON_OUTPUT_DIRECTORY}/plugins" "${CMAKE_SOURCE_DIR}/tests/src/python") - FOREACH(_in ${ARGN}) - STRING(REGEX MATCH "^([^=]+)=(.*)$" _out ${_in}) + if(WIN32) + if(NOT CMAKE_CONFIGURATION_TYPES) + set(QGIS_PYTEST_PREFIX_PATH "${QGIS_OUTPUT_DIRECTORY}/bin") + set(QGIS_PYTEST_LIBRARY_PATH "${QGIS_OUTPUT_DIRECTORY}/bin") + else() + set(QGIS_PYTEST_PREFIX_PATH "${QGIS_OUTPUT_DIRECTORY}/bin/$") + set(QGIS_PYTEST_LIBRARY_PATH "${QGIS_OUTPUT_DIRECTORY}/bin/$") + endif() + set(QGIS_PYTEST_PYTHONPATH "${_QGIS_PYTEST_PYTHONPATHS}") + else() + set(QGIS_PYTEST_PREFIX_PATH "${QGIS_OUTPUT_DIRECTORY}") + set(QGIS_PYTEST_LIBRARY_PATH "${QGIS_PYTEST_PYENV}${QGIS_OUTPUT_DIRECTORY}/lib") + string(REPLACE ";" ":" QGIS_PYTEST_PYTHONPATH "${_QGIS_PYTEST_PYTHONPATHS}") + endif() - IF("${CMAKE_MATCH_1}" STREQUAL "TEST_TIMEOUT") - SET(TEST_TIMEOUT ${CMAKE_MATCH_2}) - # Remove TEST_TIMEOUT=VALUE from the list of optional parameters - STRING(REPLACE "${CMAKE_MATCH_1}=${CMAKE_MATCH_2}" "" wo_semicolon ${wo_semicolon}) - ELSE() - MESSAGE(STATUS "ENV: SET(ENV{${CMAKE_MATCH_1}} \"${CMAKE_MATCH_2}\")") - FILE(APPEND ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " - SET(ENV{${CMAKE_MATCH_1}} \"${CMAKE_MATCH_2}\") -") - ENDIF() - ENDFOREACH(_in) + set(TEST_TIMEOUT 0) + set(QGIS_PYTEST_ADDITIONAL_ENV_VARS "") + foreach(_in ${ARGN}) + string(REGEX MATCH "^([^=]+)=(.*)$" _out ${_in}) + if("${CMAKE_MATCH_1}" STREQUAL "TEST_TIMEOUT") + set(TEST_TIMEOUT ${CMAKE_MATCH_2}) + else() + message(STATUS "ENV: set(ENV{${CMAKE_MATCH_1}} \"${CMAKE_MATCH_2}\")") + set(QGIS_PYTEST_ADDITIONAL_ENV_VARS "${QGIS_PYTEST_ADDITIONAL_ENV_VARS}\nset(ENV{${CMAKE_MATCH_1}} \"${CMAKE_MATCH_2}\")") + endif() + endforeach(_in) - SET (PYTHON_TEST_WRAPPER "" CACHE STRING "Wrapper command for python tests (e.g. `timeout -sSIGSEGV 55s` to segfault after 55 seconds)") - SET (PYTHON_TEST_WRAPPER_PROCESSED ${PYTHON_TEST_WRAPPER}) - IF (${TEST_TIMEOUT} GREATER 0 AND (NOT ${PYTHON_TEST_WRAPPER} STREQUAL "")) - STRING(REGEX REPLACE "timeout -sSIGSEGV ([0-9]+)s" "timeout -sSIGSEGV ${TEST_TIMEOUT}s" PYTHON_TEST_WRAPPER_PROCESSED ${PYTHON_TEST_WRAPPER}) - ENDIF() + set (PYTHON_TEST_WRAPPER "" CACHE STRING "Wrapper command for python tests (e.g. `timeout -sSIGSEGV 55s` to segfault after 55 seconds)") + set (PYTHON_TEST_WRAPPER_PROCESSED ${PYTHON_TEST_WRAPPER}) + if (${TEST_TIMEOUT} GREATER 0 AND (NOT ${PYTHON_TEST_WRAPPER} STREQUAL "")) + string(REGEX REPLACE "timeout -sSIGSEGV ([0-9]+)s" "timeout -sSIGSEGV ${TEST_TIMEOUT}s" PYTHON_TEST_WRAPPER_PROCESSED ${PYTHON_TEST_WRAPPER}) + endif() - FILE(APPEND ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " -MESSAGE(\"export PYTHONPATH=\$ENV{PYTHONPATH}\") -MESSAGE(STATUS \"Running ${PYTHON_TEST_WRAPPER_PROCESSED} ${Python_EXECUTABLE} ${loc} ${wo_semicolon}\") -EXECUTE_PROCESS( - COMMAND ${PYTHON_TEST_WRAPPER_PROCESSED} ${Python_EXECUTABLE} ${loc} ${wo_semicolon} - RESULT_VARIABLE import_res -) -# Pass the output back to ctest -IF(import_res) - MESSAGE(FATAL_ERROR \"Test failed: \${import_res}\") -ENDIF(import_res) -" -) - IF(CMAKE_CONFIGURATION_TYPES) - ADD_TEST(NAME ${TESTNAME} COMMAND ${CMAKE_COMMAND} -D CMAKE_BUILD_TYPE=$ -P ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake) - ELSE(CMAKE_CONFIGURATION_TYPES) - ADD_TEST(NAME ${TESTNAME} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake) - ENDIF(CMAKE_CONFIGURATION_TYPES) + configure_file(${CMAKE_SOURCE_DIR}/cmake_templates/PyQgsTest.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake @ONLY NEWLINE_STYLE "LF") - IF (${TEST_TIMEOUT} GREATER 0) - SET_TESTS_PROPERTIES(${TESTNAME} PROPERTIES TIMEOUT ${TEST_TIMEOUT}) - ENDIF() + if(CMAKE_CONFIGURATION_TYPES) + add_test(NAME ${TESTNAME} COMMAND ${CMAKE_COMMAND} -D CMAKE_BUILD_TYPE=$ -P ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake) + else() + add_test(NAME ${TESTNAME} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake) + endif() -ENDMACRO(ADD_PYTHON_TEST) + if (${TEST_TIMEOUT} GREATER 0) + set_tests_properties(${TESTNAME} PROPERTIES TIMEOUT ${TEST_TIMEOUT}) + endif() -# Byte compile recursively a directory (DIRNAME) -MACRO(ADD_PYTHON_COMPILEALL_TEST DIRNAME) - # First get the path: - GET_FILENAME_COMPONENT(temp_path "${PYTHON_LIBRARIES}" PATH) - # Find the python script: - GET_FILENAME_COMPONENT(PYTHON_COMPILE_ALL_PY "${temp_path}/../compileall.py" ABSOLUTE) - # add test, use DIRNAME to create unique name for the test: - ADD_TEST(COMPILE_ALL-${DIRNAME} ${Python_EXECUTABLE} "${PYTHON_COMPILE_ALL_PY}" -q ${DIRNAME}) -ENDMACRO(ADD_PYTHON_COMPILEALL_TEST) +endmacro(ADD_PYTHON_TEST) diff --git a/cmake_templates/PyQgsTest.cmake.in b/cmake_templates/PyQgsTest.cmake.in new file mode 100644 index 00000000000..75d01cda703 --- /dev/null +++ b/cmake_templates/PyQgsTest.cmake.in @@ -0,0 +1,24 @@ + +set(ENV{QGIS_PREFIX_PATH} "@QGIS_PYTEST_PREFIX_PATH@") +if(WIN32) + set(ENV{PATH} "@QGIS_PYTEST_LIBRARY_PATH@;$ENV{PATH}") + set(ENV{PYTHONPATH} "@QGIS_PYTEST_PYTHONPATH@;$ENV{PYTHONPATH}") +else() + set(ENV{LD_LIBRARY_PATH} "@QGIS_PYTEST_LIBRARY_PATH@:$ENV{LD_LIBRARY_PATH}") + set(ENV{PYTHONPATH} "@QGIS_PYTEST_PYTHONPATH@:$ENV{PYTHONPATH}") +endif() + +@QGIS_PYTEST_ADDITIONAL_ENV_VARS@ + +message("export @QGIS_PYTEST_PATH_VAR_NAME@=$ENV{@QGIS_PYTEST_PATH_VAR_NAME@}") +message("export PYTHONPATH=$ENV{PYTHONPATH}") + +message(STATUS "Running @PYTHON_TEST_WRAPPER_PROCESSED@ @Python_EXECUTABLE@ @QGIS_PYTEST_FILE_LOC@") +execute_process( + COMMAND @PYTHON_TEST_WRAPPER_PROCESSED@ @Python_EXECUTABLE@ @QGIS_PYTEST_FILE_LOC@ + RESULT_VARIABLE import_res +) +# Pass the output back to ctest +if(import_res) + message(FATAL_ERROR "Test failed: ${import_res}") +endif()