From d054a2bccf622f5232c626516327eaad1de3c844 Mon Sep 17 00:00:00 2001
From: Timo Koch <timo.koch@iws.uni-stuttgart.de>
Date: Fri, 18 Oct 2019 11:59:36 +0200
Subject: [PATCH] [cmake] Implement Dune 2.6 backwards-compatible
 dumux_add_test

---
 cmake/modules/DumuxTestMacros.cmake | 329 +++++++++++++++++++++++++++-
 1 file changed, 327 insertions(+), 2 deletions(-)

diff --git a/cmake/modules/DumuxTestMacros.cmake b/cmake/modules/DumuxTestMacros.cmake
index fd437823f1..adc99917e2 100644
--- a/cmake/modules/DumuxTestMacros.cmake
+++ b/cmake/modules/DumuxTestMacros.cmake
@@ -14,7 +14,7 @@
 ###
 macro(add_dumux_test dumux_test dumux_test_executable dumux_test_executable_source)
 
-  message(WARNING "add_dumux_test is deprecated. Use dune_add_test directly now that we require dune 2.6")
+  message(WARNING "add_dumux_test is deprecated. Use dumux_add_test now that we require dune 2.6")
 
   # if present, symlink the grids folder
   set(grids_directory ${CMAKE_CURRENT_SOURCE_DIR}/grids)
@@ -48,10 +48,335 @@ macro(add_dumux_test dumux_test dumux_test_executable dumux_test_executable_sour
   # add test
   list(GET dumux_test_args 0 dumux_test_command)
   list(REMOVE_AT dumux_test_args 0)
-  dune_add_test(NAME ${dumux_test}
+  dumux_add_test(NAME ${dumux_test}
                 TARGET ${dumux_test_executable}
                 COMMAND ${dumux_test_command}
                 CMD_ARGS ${dumux_test_args})
   # tests always require the executable to run
   set_tests_properties(${dumux_test} PROPERTIES REQUIRED_FILES ${dumux_test_executable})
 endmacro()
+
+# Dumux wrapper for the module that provides tools for testing the Dune way.
+# We have a wrapper to have to possibily of supporting multiple Dune versions.
+#
+# .. cmake_function:: dumux_declare_test_label
+#
+#    .. cmake_brief::
+#
+#       Declare labels for :ref:`dumux_add_test`.
+#
+#    .. cmake_param:: LABELS
+#       :multi:
+#
+#       The names of labels to declare.  Label names must be nonempty and
+#       consist only of alphanumeric characters plus :code:`-` and :code:`_`
+#       to make sure it is easy to construct regular expressions from them for
+#       :code:`ctest -L ${label_regex}`.
+#
+#    Labels need to be declared to ensure that the target
+#    :code:`build_${label}_tests` exists.  They will normally be declared
+#    on-demand by :ref:`dumux_add_test`.  But sometimes it is useful to be able to
+#    run :code:`make build_${label}_tests` whether or not any tests with that
+#    label exists in a module.  For these cases :ref:`dune_declare_test_label` can
+#    be called explicitly.
+#
+#    The label :code:`quick` is always predeclared.
+#
+# .. cmake_function:: dumux_add_test
+#
+#    .. cmake_brief::
+#
+#       Adds a test to the Dumux testing suite!
+#
+#    .. cmake_param:: NAME
+#       :single:
+#
+#       The name of the test that should be added. If an executable
+#       is also added (by specifying SOURCES), the executable is also
+#       named accordingly. If omitted, the name will be deduced from
+#       the (single) sources parameter or from the given target. Note
+#       that this requires you to take care, that you only use a target
+#       or source file for but one such test.
+#
+#    .. cmake_param:: SOURCES
+#       :multi:
+#
+#       The source files that this test depends on. These are the
+#       sources that will be passed to :ref:`add_executable`.
+#
+#       You *must* specify either :code:`SOURCES` or :code:`TARGET`.
+#
+#    .. cmake_param:: TARGET
+#       :single:
+#
+#       An executable target which should be used for the test. Use
+#       this option over the :code:`SOURCES` parameter if you want to
+#       reuse already added targets.
+#
+#       You *must* specify either :code:`SOURCES` or :code:`TARGET`.
+#
+#    .. cmake_param:: COMPILE_DEFINITIONS
+#       :multi:
+#       :argname: def
+#
+#       A set of compile definitions to add to the target.
+#       Only definitions beyond the application of :ref:`add_dune_all_flags`
+#       have to be stated.
+#       This is only used, if :code:`dumux_add_test` adds the executable itself.
+#
+#    .. cmake_param:: COMPILE_FLAGS
+#       :multi:
+#       :argname: flag
+#
+#       A set of non-definition compile flags to add to the target.
+#       Only flags beyond the application of :ref:`add_dune_all_flags`
+#       have to be stated.
+#       This is only used, if :code:`dumux_add_test` adds the executable itself.
+#
+#    .. cmake_param:: LINK_LIBRARIES
+#       :multi:
+#       :argname: lib
+#
+#       A list of libraries to link the target to.
+#       Only libraries beyond the application of :ref:`add_dune_all_flags`
+#       have to be stated.
+#       This is only used, if :code:`dumux_add_test` adds the executable itself.
+#
+#    .. cmake_param:: EXPECT_COMPILE_FAIL
+#       :option:
+#
+#       If given, the test is expected to not compile successfully!
+#
+#    .. cmake_param:: EXPECT_FAIL
+#       :option:
+#
+#       If given, this test is expected to compile, but fail to run.
+#
+#    .. cmake_param:: CMD_ARGS
+#       :multi:
+#       :argname: arg
+#
+#       Command line arguments that should be passed to this test.
+#
+#    .. cmake_param:: MPI_RANKS
+#       :multi:
+#       :argname: ranks
+#
+#       The numbers of cores that this test should be executed with.
+#       Note that one test (in the ctest sense) is created for each number
+#       given here. Any number exceeding the user-specified processor maximum
+#       :ref:`DUNE_MAX_TEST_CORES` will be ignored. Tests with a
+#       processor number :code:`n` higher than one will have the suffix
+#       :code:`-mpi-n` appended to their name. You need to specify the
+#       TIMEOUT option when specifying the MPI_RANKS option.
+#
+#    .. cmake_param:: CMAKE_GUARD
+#       :multi:
+#       :argname: condition
+#
+#       A number of conditions that CMake should evaluate before adding this
+#       test. If one of the conditions fails, the test should be shown
+#       as skipped in the test summary. Use this feature instead of guarding
+#       the call to :code:`dumux_add_test` with an :code:`if` clause.
+#
+#       The passed condition can be a complex expression like
+#       `( A OR B ) AND ( C OR D )`. Mind the spaces around the parentheses.
+#
+#       Example: Write CMAKE_GUARD dune-foo_FOUND if you want your test to only
+#       build and run when the dune-foo module is present.
+#
+#    .. cmake_param:: COMMAND
+#       :multi:
+#       :argname: cmd
+#
+#       You may specify the COMMAND option to give the exact command line to be
+#       executed when running the test. This defaults to the name of the executable
+#       added by dumux_add_test for this test. Note that if you specify both CMD_ARGS
+#       and COMMAND, the given CMD_ARGS will be put behind your COMMAND. If you use
+#       this in combination with the MPI_RANKS parameter, the call to mpi will still be
+#       wrapped around the given commands.
+#
+#    .. cmake_param:: COMPILE_ONLY
+#       :option:
+#
+#       Set if the given test should only be compiled during :code:`make build_tests`,
+#       but not run during :code:`make test`. This is useful if you compile the same
+#       executable twice, but with different compile flags, where you want to assure that
+#       it compiles with both sets of flags, but you already know they will produce the
+#       same result.
+#
+#    .. cmake_param:: TIMEOUT
+#       :single:
+#
+#       If set, the test will time out after the given number of seconds. This supersedes
+#       any timeout setting in ctest (see `cmake --help-property TIMEOUT`). If you
+#       specify the MPI_RANKS option, you need to specify a TIMEOUT.
+#
+#    .. cmake_param:: LABELS
+#       :multi:
+#
+#       A list of labels to add to the test.  This has two effects: it sets
+#       the LABELS property on the test so :code:`ctest -L ${label_regex}` can
+#       be used to run all tests with certain labels.  It also adds any
+#       targets created as dependencies to a custom target, so you can build
+#       all tests with a particular label by doing :code:`make
+#       build_${label}_tests` without having to build all the other tests as
+#       well.
+#
+#       The :code:`build_${label}_tests` targets are created on-demand the
+#       first time a test with that label is added.  In some situations it can
+#       depend on the values of cmake cache variables whether a test is added,
+#       and then it can happen that the :code:`build_${target}_tests` target
+#       exists only sometimes.  If your workflow relies on the existance of
+#       these targets, even if building them just returns successfully without
+#       doing anything, you can ensure they exist by calling
+#       :ref:`dune_declare_test_label` unconditionally.  The label
+#       :code:`quick` is always predeclared in this way.
+#
+#       The label names must be non-empty, and must only contain alphanumeric
+#       characters other than :code:`-` or :code:`_`.  This restriction is in
+#       place to make it easy to construct regular expressions from the label
+#       names for :code:`ctest -L ${label_regex}`.
+#
+#    This function defines the Dune way of adding a test to the testing suite.
+#    You may either add the executable yourself through :ref:`add_executable`
+#    and pass it to the :code:`TARGET` option, or you may rely on :ref:`dumux_add_test`
+#    to do so.
+#
+# .. cmake_variable:: DUNE_REENABLE_ADD_TEST
+#
+#    You may set this variable to True either through your opts file or in your module
+#    (before the call to :code:`include(DuneMacros)`) to suppress the error that is thrown if
+#    :code:`add_test` is used. You should only do that if you have proper reason to do so.
+#
+# .. cmake_variable:: DUNE_MAX_TEST_CORES
+#
+#    You may set this variable to give an upperbound to the number of processors, that
+#    a single test may use. Defaults to 2, when MPI is found and to 1 otherwise.
+#
+# .. cmake_variable:: DUNE_BUILD_TESTS_ON_MAKE_ALL
+#
+#    You may set this variable through your opts file or on a per module level (in the toplevel
+#    :code:`CMakeLists.txt` before :code:`include(DuneMacros)`) to have the Dune build system
+#    build all tests during `make all`. Note, that this may take quite some time for some modules.
+#    If not in use, you have to build tests through the target :code:`build_tests`.
+#
+
+# Note: This is a copy of dune_declare_test_label to be backwards compatible with Dune 2.6 but enable labels
+function(dumux_declare_test_label)
+  include(CMakeParseArguments)
+  set(OPTIONS)
+  set(SINGLEARGS)
+  set(MULTIARGS LABELS)
+  cmake_parse_arguments(arg "${OPTIONS}" "${SINGLEARGS}" "${MULTIARGS}" ${ARGN})
+
+  if( (DEFINED arg_UNPARSED_ARGUMENTS) AND NOT ( arg_UNPARSED_ARGUMENTS STREQUAL "" ) )
+    message(FATAL_ERROR "Unhandled extra arguments given to dumux_declare_test_label(): "
+      "<${arg_UNPARSED_ARGUMENTS}>")
+  endif()
+
+  foreach(label IN LISTS arg_LABELS)
+    # Make sure the label is not empty, and does not contain any funny
+    # characters, in particular regex characters
+    if(NOT (label MATCHES "[-_0-9a-zA-Z]+"))
+      message(FATAL_ERROR "Refusing to add label \"${label}\" since it is "
+        "empty or contains funny characters (characters other than "
+        "alphanumeric ones and \"-\" or \"_\"; the intent of this restriction "
+        "is to make construction of the argument to \"ctest -L\" easier")
+    endif()
+    set(target "build_${label}_tests")
+    if(NOT TARGET "${target}")
+      add_custom_target("${target}")
+    endif()
+  endforeach()
+endfunction(dumux_declare_test_label)
+
+# predefine "quick" test label so build_quick_tests can be built
+# unconditionally
+dumux_declare_test_label(LABELS quick)
+
+# Note: This is a copy of dune_declare_test_label to be backwards compatible with Dune 2.6 but enable labels
+# After labels are available on a release branch this can simply forward to dune_add_test
+function(dumux_add_test)
+  # for new versions just forward to dune_add_test
+  if(DUNE_COMMON_VERSION VERSION_GREATER 2.6.0)
+    dune_add_test(${ARGV})
+
+  # otherwise deal with labels separately (backwards-compatibilty layer with Dune 2.6.0)
+  else()
+    include(CMakeParseArguments)
+    set(OPTIONS EXPECT_COMPILE_FAIL EXPECT_FAIL SKIP_ON_77 COMPILE_ONLY)
+    set(SINGLEARGS NAME TARGET TIMEOUT)
+    set(MULTIARGS SOURCES COMPILE_DEFINITIONS COMPILE_FLAGS LINK_LIBRARIES CMD_ARGS MPI_RANKS COMMAND CMAKE_GUARD LABELS)
+    cmake_parse_arguments(ADDTEST "${OPTIONS}" "${SINGLEARGS}" "${MULTIARGS}" ${ARGN})
+
+    # Check whether the parser produced any errors
+    if(ADDTEST_UNPARSED_ARGUMENTS)
+      message(WARNING "Unrecognized arguments ('${ADDTEST_UNPARSED_ARGUMENTS}') for dumux_add_test!")
+    endif()
+
+    # remove labels from the argument list
+    set(FORWARD_ARGS ${ARGV})
+    if(ADDTEST_LABELS)
+      string(REPLACE "LABELS;${ADDTEST_LABELS}" "" FORWARD_ARGS "${FORWARD_ARGS}")
+      # replace head or trailing ";"
+      string(REGEX REPLACE ";^" "" FORWARD_ARGS "${FORWARD_ARGS}")
+      string(REGEX REPLACE ";$" "" FORWARD_ARGS "${FORWARD_ARGS}")
+    endif()
+
+    # foward to dune function
+    dune_add_test(${FORWARD_ARGS})
+
+    # take care of labels afterwards
+    if(NOT ADDTEST_NAME)
+      # try deducing the test name from the executable name
+      if(ADDTEST_TARGET)
+        set(ADDTEST_NAME ${ADDTEST_TARGET})
+      endif()
+      # try deducing the test name form the source name
+      if(ADDTEST_SOURCES)
+        list(LENGTH ADDTEST_SOURCES len)
+        get_filename_component(ADDTEST_NAME ${ADDTEST_SOURCES} NAME_WE)
+      endif()
+    endif()
+
+    if(ADDTEST_SOURCES)
+      set(ADDTEST_TARGET ${ADDTEST_NAME})
+    endif()
+
+    # possibly set default for mpi ranks
+    if(NOT ADDTEST_MPI_RANKS)
+      set(ADDTEST_MPI_RANKS 1)
+    endif()
+
+    # Discard all parallel tests if MPI was not found
+    if(NOT MPI_FOUND)
+      set(DUNE_MAX_TEST_CORES 1)
+    endif()
+
+    # make sure each label exists and its name is acceptable
+    dumux_declare_test_label(LABELS ${ADDTEST_LABELS})
+
+    # Have build_${label}_tests depend on the given target in
+    # order to trigger the build correctly
+    if(NOT ADDTEST_EXPECT_COMPILE_FAIL)
+      foreach(label IN LISTS ADDTEST_LABELS)
+        add_dependencies(build_${label}_tests ${ADDTEST_TARGET})
+      endforeach()
+    endif()
+
+    # Add one test for each specified processor number
+    foreach(procnum ${ADDTEST_MPI_RANKS})
+      if((NOT "${procnum}" GREATER "${DUNE_MAX_TEST_CORES}") AND (NOT ADDTEST_COMPILE_ONLY))
+        set(ACTUAL_NAME ${ADDTEST_NAME})
+
+        if(NOT ${procnum} STREQUAL "1")
+          set(ACTUAL_NAME "${ACTUAL_NAME}-mpi-${procnum}")
+        endif()
+
+        # Set the labels on the test
+        set_tests_properties(${ACTUAL_NAME} PROPERTIES LABELS "${ADDTEST_LABELS}")
+      endif()
+    endforeach()
+  endif()
+endfunction()
-- 
GitLab