From f96461f353719d30621b99b66638ce4b2033c4e5 Mon Sep 17 00:00:00 2001
From: Lars Bilke <lars.bilke@ufz.de>
Date: Wed, 30 Sep 2020 13:17:36 +0200
Subject: [PATCH] [CMake] Added arguments PYTHON_PACKAGES and
 WORKING_DIRECTORY_SOURCE to AddTest()

Default working directory for tests was changed from source to binary dir.

- PYTHON_PACKAGES allows for specification of additional Python module dependencies. Requires the poetry-tool and specifying the 'poetry'-wrapper.
- WORKING_DIRECTORY_SOURCE reverts to previous behavior of running the tests in the source tree. Also adapted MeshTest() for this.
---
 scripts/cmake/test/AddTest.cmake        | 49 +++++++++++++++++++------
 scripts/cmake/test/AddTestWrapper.cmake | 21 ++---------
 scripts/cmake/test/MeshTest.cmake       | 10 ++++-
 3 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/scripts/cmake/test/AddTest.cmake b/scripts/cmake/test/AddTest.cmake
index e47de17eca9..2659fe9abc0 100644
--- a/scripts/cmake/test/AddTest.cmake
+++ b/scripts/cmake/test/AddTest.cmake
@@ -15,9 +15,11 @@
 #   REQUIREMENTS # optional simple boolean expression which has to be true to
 #                  enable the test, e.g.
 #                  OGS_USE_PETSC AND (OGS_USE_EIGEN OR OGS_USE_LIS)
+#   PYTHON_PACKAGES package_x=1.2.3 package_y=0.1.x # optional
 #   VIS <vtu output file(s)> # optional for documentation
 #   RUNTIME <in seconds> # optional for optimizing ctest duration
 #                          values should be taken from envinf job
+#   WORKING_DIRECTORY_SOURCE # optional, runs the the test in the source directory
 #   DISABLED # optional, disables the test
 # )
 #
@@ -44,9 +46,9 @@ function (AddTest)
     set(LARGE_RUNTIME 60)
 
     # parse arguments
-    set(options DISABLED)
+    set(options DISABLED WORKING_DIRECTORY_SOURCE)
     set(oneValueArgs EXECUTABLE PATH NAME WRAPPER TESTER ABSTOL RELTOL RUNTIME DEPENDS)
-    set(multiValueArgs EXECUTABLE_ARGS DATA DIFF_DATA WRAPPER_ARGS REQUIREMENTS VIS)
+    set(multiValueArgs EXECUTABLE_ARGS DATA DIFF_DATA WRAPPER_ARGS REQUIREMENTS PYTHON_PACKAGES VIS)
     cmake_parse_arguments(AddTest "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
 
@@ -66,9 +68,15 @@ function (AddTest)
     if (NOT DEFINED AddTest_RUNTIME)
         set(AddTest_RUNTIME 1)
     endif()
+    if(AddTest_WORKING_DIRECTORY_SOURCE)
+        set(AddTest_WORKING_DIRECTORY ${AddTest_SOURCE_PATH})
+    else()
+        set(AddTest_WORKING_DIRECTORY ${AddTest_BINARY_PATH})
+    endif()
 
     if("${AddTest_EXECUTABLE}" STREQUAL "ogs")
-        set(AddTest_EXECUTABLE_ARGS -o ${AddTest_BINARY_PATH_NATIVE} ${AddTest_EXECUTABLE_ARGS})
+        set(AddTest_EXECUTABLE_ARGS -o ${AddTest_BINARY_PATH_NATIVE}
+            ${AddTest_SOURCE_PATH}/${AddTest_EXECUTABLE_ARGS})
     endif()
 
     if(${AddTest_RUNTIME} GREATER ${LARGE_RUNTIME})
@@ -120,6 +128,13 @@ function (AddTest)
             message(STATUS "ERROR: mpirun was not found but is required for ${AddTest_NAME}!")
             return()
         endif()
+    elseif(AddTest_WRAPPER STREQUAL "poetry")
+        if(POETRY)
+            set(WRAPPER_COMMAND ${POETRY})
+            set(AddTest_WRAPPER_ARGS "run")
+        else()
+            set(DISABLED_TESTS_LOG "${DISABLED_TESTS_LOG}\nDisabling poetry wrapper for ${AddTest_NAME} as poetry exe was not found!" CACHE INTERNAL "")
+        endif()
     endif()
 
     # --- Implement testers ---
@@ -251,24 +266,18 @@ Use six arguments version of AddTest with absolute and relative tolerances")
         COMMAND ${CMAKE_COMMAND}
         -DEXECUTABLE=${AddTest_EXECUTABLE_PARSED}
         "-DEXECUTABLE_ARGS=${AddTest_EXECUTABLE_ARGS}" # Quoted because passed as list
-        -DSOURCE_PATH=${AddTest_SOURCE_PATH}           # see https://stackoverflow.com/a/33248574/80480
+                                                       # see https://stackoverflow.com/a/33248574/80480
         -DBINARY_PATH=${AddTest_BINARY_PATH}
         -DWRAPPER_COMMAND=${WRAPPER_COMMAND}
         "-DWRAPPER_ARGS=${AddTest_WRAPPER_ARGS}"
         "-DFILES_TO_DELETE=${FILES_TO_DELETE}"
         -DPython3_EXECUTABLE=${Python3_EXECUTABLE}
+        -DWORKING_DIRECTORY=${AddTest_WORKING_DIRECTORY}
         -P ${PROJECT_SOURCE_DIR}/scripts/cmake/test/AddTestWrapper.cmake
     )
     if(DEFINED AddTest_DEPENDS)
         set_tests_properties(${TEST_NAME} PROPERTIES DEPENDS ${AddTest_DEPENDS})
     endif()
-    if(EXISTS ${AddTest_SOURCE_PATH}/requirements.txt)
-        set(PYTHONPATH "${AddTest_BINARY_PATH}/.venv/lib/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages")
-        if(WIN32)
-            set(PYTHONPATH "${AddTest_BINARY_PATH}/.venv/Lib/site-packages")
-        endif()
-        set_tests_properties(${TEST_NAME} PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHONPATH}")
-    endif()
     if(DEFINED MPI_PROCESSORS)
         set_tests_properties(${TEST_NAME} PROPERTIES PROCESSORS ${MPI_PROCESSORS})
     endif()
@@ -285,6 +294,24 @@ Use six arguments version of AddTest with absolute and relative tolerances")
         add_dependencies(ctest-large ${AddTest_EXECUTABLE})
     endif()
 
+    if(AddTest_PYTHON_PACKAGES)
+        if(NOT AddTest_WRAPPER STREQUAL "poetry")
+            message(FATAL_ERROR "Benchmark ${AddTest_NAME} uses PYTHON_PACKAGES"
+                ", make sure to have the WRAPPER set to 'poetry'!")
+        endif()
+        if(POETRY)
+            execute_process(
+               COMMAND poetry add ${AddTest_PYTHON_PACKAGES}
+               WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
+            )
+        else()
+            message(STATUS "Warning: Benchmark ${AddTest_NAME} requires these "
+                "Python packages: ${AddTest_PYTHON_PACKAGES}!\n Make sure to "
+                "have them installed in your current Python environment OR "
+                "install the Poetry package manager for Python!")
+        endif()
+    endif()
+
     if(NOT AddTest_TESTER OR OGS_COVERAGE)
         return()
     endif()
diff --git a/scripts/cmake/test/AddTestWrapper.cmake b/scripts/cmake/test/AddTestWrapper.cmake
index 9152c9f0924..c8d801d698c 100644
--- a/scripts/cmake/test/AddTestWrapper.cmake
+++ b/scripts/cmake/test/AddTestWrapper.cmake
@@ -4,26 +4,13 @@ foreach(FILE ${FILES_TO_DELETE})
     file(REMOVE ${BINARY_PATH}/${FILE})
 endforeach()
 
-# Create Python virtual environment and install packages
-set(PIP .venv/bin/pip)
-if(WIN32)
-    set(PIP .venv/Scripts/pip.exe)
-endif()
-if(EXISTS ${SOURCE_PATH}/requirements.txt AND NOT EXISTS ${BINARY_PATH}/${PIP})
-    message(STATUS "Generating Python virtual environment...")
-    execute_process(
-        COMMAND virtualenv --python ${Python3_EXECUTABLE} .venv
-        WORKING_DIRECTORY ${BINARY_PATH})
-endif()
-if(EXISTS ${SOURCE_PATH}/requirements.txt)
-    execute_process(
-        COMMAND ${PIP} install -r ${SOURCE_PATH}/requirements.txt
-        WORKING_DIRECTORY ${BINARY_PATH})
-endif()
+string(REPLACE ";" " " CMD_STRING "cd ${WORKING_DIRECTORY} && ${WRAPPER_COMMAND} "
+"${WRAPPER_ARGS} ${EXECUTABLE} ${EXECUTABLE_ARGS}")
+message(STATUS "Test command cleaned:\n${CMD_STRING}")
 
 execute_process(
     COMMAND ${WRAPPER_COMMAND} ${WRAPPER_ARGS} ${EXECUTABLE} ${EXECUTABLE_ARGS}
-    WORKING_DIRECTORY ${SOURCE_PATH}
+    WORKING_DIRECTORY ${WORKING_DIRECTORY}
     RESULT_VARIABLE EXIT_CODE
     OUTPUT_VARIABLE OUTPUT
     ERROR_VARIABLE OUTPUT
diff --git a/scripts/cmake/test/MeshTest.cmake b/scripts/cmake/test/MeshTest.cmake
index e0a61410d20..8505da00d45 100644
--- a/scripts/cmake/test/MeshTest.cmake
+++ b/scripts/cmake/test/MeshTest.cmake
@@ -21,7 +21,7 @@ function (MeshTest)
         return()
     endif()
     # parse arguments
-    set(options NONE)
+    set(options WORKING_DIRECTORY_SOURCE)
     set(oneValueArgs EXECUTABLE PATH NAME WRAPPER RUNTIME)
     set(multiValueArgs EXECUTABLE_ARGS DATA DIFF_DATA WRAPPER_ARGS REQUIREMENTS)
     cmake_parse_arguments(MeshTest "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -32,6 +32,11 @@ function (MeshTest)
     file(MAKE_DIRECTORY ${MeshTest_BINARY_PATH})
     file(TO_NATIVE_PATH "${MeshTest_BINARY_PATH}" MeshTest_BINARY_PATH_NATIVE)
     set(MeshTest_STDOUT_FILE_PATH "${MeshTest_BINARY_PATH}/${MeshTest_NAME}_stdout.log")
+    if(MeshTest_WORKING_DIRECTORY_SOURCE)
+        set(MeshTest_WORKING_DIRECTORY ${MeshTest_SOURCE_PATH})
+    else()
+        set(MeshTest_WORKING_DIRECTORY ${MeshTest_BINARY_PATH})
+    endif()
 
     # set defaults
     if (NOT DEFINED MeshTest_REQUIREMENTS)
@@ -140,12 +145,13 @@ function (MeshTest)
         COMMAND ${CMAKE_COMMAND}
         -DEXECUTABLE=${MeshTest_EXECUTABLE_PARSED}
         "-DEXECUTABLE_ARGS=${MeshTest_EXECUTABLE_ARGS}" # Quoted because passed as list
-        -DSOURCE_PATH=${MeshTest_SOURCE_PATH}             # see https://stackoverflow.com/a/33248574/80480
+                                                        # see https://stackoverflow.com/a/33248574/80480
         -DBINARY_PATH=${MeshTest_BINARY_PATH}
         -DWRAPPER_COMMAND=${WRAPPER_COMMAND}
         "-DWRAPPER_ARGS=${MeshTest_WRAPPER_ARGS}"
         "-DFILES_TO_DELETE=${FILES_TO_DELETE}"
         -DSTDOUT_FILE_PATH=${MeshTest_STDOUT_FILE_PATH}
+        -DWORKING_DIRECTORY=${MeshTest_WORKING_DIRECTORY}
         -P ${PROJECT_SOURCE_DIR}/scripts/cmake/test/AddTestWrapper.cmake
     )
     set_tests_properties(${TEST_NAME} PROPERTIES COST ${MeshTest_RUNTIME})
-- 
GitLab