BASIS  r3148
BasisTest.cmake
Go to the documentation of this file.
00001 ##############################################################################
00002 # @file  BasisTest.cmake
00003 # @brief CTest configuration. Include this module instead of CTest.
00004 #
00005 # @note This module is included by basis_project_initialize().
00006 #
00007 # Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br />
00008 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00009 #
00010 # Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00011 #
00012 # @ingroup CMakeAPI
00013 ##############################################################################
00014 
00015 # ============================================================================
00016 # configuration
00017 # ============================================================================
00018 
00019 ## @brief Request build of tests.
00020 option (BUILD_TESTING "Request build of tests." OFF)
00021 
00022 # include CTest module which enables testing, but prevent it from generating
00023 # any configuration file or adding targets yet as we want to adjust the
00024 # default CTest settings--in particular the site name--before
00025 set (RUN_FROM_DART 1)
00026 include (CTest)
00027 
00028 # mark timeout option as advanced
00029 mark_as_advanced (DART_TESTING_TIMEOUT)
00030 
00031 set (RUN_FROM_CTEST_OR_DART 1)
00032 include (CTestTargets)
00033 set (RUN_FROM_CTEST_OR_DART)
00034 
00035 # custom CTest configuration
00036 if (EXISTS "${PROJECT_CONFIG_DIR}/CTestCustom.cmake.in")
00037   configure_file (
00038     "${PROJECT_CONFIG_DIR}/CTestCustom.cmake.in"
00039     "${PROJECT_BINARY_DIR}/CTestCustom.cmake"
00040     @ONLY
00041   )
00042 elseif (EXISTS "${PROJECT_CONFIG_DIR}/CTestCustom.cmake")
00043   configure_file (
00044     "${PROJECT_CONFIG_DIR}/CTestCustom.cmake"
00045     "${PROJECT_BINARY_DIR}/CTestCustom.cmake"
00046     COPYONLY
00047   )
00048 else ()
00049   basis_get_relative_path (CONFIG_DIR "${PROJECT_SOURCE_DIR}" "${PROJECT_CONFIG_DIR}")
00050   if (EXISTS "${BASIS_TEMPLATE_DIR}/${CONFIG_DIR}/CTestCustom.cmake.in")
00051     # to avoid a Doxygen warning, we need to replace certain patterns used by
00052     # the basisproject tool to replace them with project related information
00053     #
00054     # Note: Do this only on the first pass, otherwise configure_file() will
00055     #       retrigger CMake every time b/c the modification timestamp of the
00056     #       source file is newer than the previously configured file.
00057     #       The use of the "cmake -E copy_if_different" command could be used
00058     #       here instead, but as we do not expect the CTestCustom.cmake.in
00059     #       file of the BASIS project template to change, it is sufficient
00060     #       to only check if we copied the template file already.
00061     if (NOT EXISTS "${PROJECT_BINARY_DIR}/CTestCustom.cmake.in")
00062       file (READ "${BASIS_TEMPLATE_DIR}/${CONFIG_DIR}/CTestCustom.cmake.in" _TEMPLATE)
00063       string (REGEX REPLACE "<year>" "" _TEMPLATE "${_TEMPLATE}")
00064       file (WRITE "${PROJECT_BINARY_DIR}/CTestCustom.cmake.in" "${_TEMPLATE}")
00065       unset (_TEMPLATE)
00066     endif ()
00067     # configure the modified template file
00068     configure_file (
00069       "${PROJECT_BINARY_DIR}/CTestCustom.cmake.in"
00070       "${PROJECT_BINARY_DIR}/CTestCustom.cmake"
00071       @ONLY
00072     )
00073   endif ()
00074 endif ()
00075 
00076 # ============================================================================
00077 # constants
00078 # ============================================================================
00079 
00080 ## @brief Names of recognized properties on tests.
00081 #
00082 # Unfortunately, the @c ARGV and @c ARGN arguments of a CMake function()
00083 # or macro() does not preserve values which themselves are lists. Therefore,
00084 # it is not possible to distinguish between property names and their values
00085 # in the arguments passed to basis_set_tests_properties().
00086 # To overcome this problem, this list specifies all the possible property names.
00087 # Everything else is considered to be a property value except the first argument
00088 # follwing right after the @c PROPERTIES keyword. Alternatively,
00089 # basis_set_property() can be used as here no disambiguity exists.
00090 #
00091 # @note Placeholders such as &lt;CONFIG&gt; are allowed. These are treated
00092 #       as the regular expression "[^ ]+". See basis_list_to_regex().
00093 #
00094 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#section_PropertiesonTests
00095 set (BASIS_PROPERTIES_ON_TESTS
00096   ATTACHED_FILES
00097   ATTACHED_FILES_ON_FAIL
00098   COST
00099   DEPENDS
00100   ENVIRONMENT
00101   FAIL_REGULAR_EXPRESSION
00102   LABELS
00103   MEASUREMENT
00104   PASS_REGULAR_EXPRESSION
00105   PROCESSORS
00106   REQUIRED_FILES
00107   RESOURCE_LOCK
00108   RUN_SERIAL
00109   TIMEOUT
00110   WILL_FAIL
00111   WORKING_DIRECTORY
00112 )
00113 
00114 # convert list into regular expression
00115 basis_list_to_regex (BASIS_PROPERTIES_ON_TESTS_RE ${BASIS_PROPERTIES_ON_TESTS})
00116 
00117 # ============================================================================
00118 # utilities
00119 # ============================================================================
00120 
00121 ## @addtogroup CMakeUtilities
00122 #  @{
00123 
00124 
00125 # ----------------------------------------------------------------------------
00126 ## @brief Disable testing if project does not implement any tests.
00127 #
00128 # This function checks if there are test/ subdirectories in the project and
00129 # disables and hides the BUILD_TESTING option if none are found.
00130 function (basis_disable_testing_if_no_tests)
00131   if (IS_DIRECTORY "${PROJECT_TESTING_DIR}")
00132     set (DISABLE_TESTING FALSE)
00133   else ()
00134     set (DISABLE_TESTING TRUE)
00135   endif ()
00136   if (DISABLE_TESTING)
00137     basis_get_relative_path (TESTING_DIR "${PROJECT_SOURCE_DIR}" "${PROJECT_TESTING_DIR}")
00138     foreach (M IN LISTS PROJECT_MODULES_ENABLED)
00139       if (IS_DIRECTORY "${MODULE_${M}_SOURCE_DIR}/${TESTING_DIR}")
00140         set (DISABLE_TESTING FALSE)
00141         break ()
00142       endif ()
00143     endforeach ()
00144   endif ()
00145   if (DISABLE_TESTING)
00146     set_property (CACHE BUILD_TESTING PROPERTY VALUE OFF)
00147     set_property (CACHE BUILD_TESTING PROPERTY TYPE  INTERNAL)
00148   else ()
00149     set_property (CACHE BUILD_TESTING PROPERTY TYPE BOOL)
00150   endif ()
00151 endfunction ()
00152 
00153 # ----------------------------------------------------------------------------
00154 ## @brief Set a property of the tests.
00155 #
00156 # This function replaces CMake's
00157 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_tests_properties">
00158 # set_tests_properties()</a> command.
00159 #
00160 # @note Due to a bug in CMake (http://www.cmake.org/Bug/view.php?id=12303),
00161 #       except of the first property given directly after the @c PROPERTIES keyword,
00162 #       only properties listed in @c BASIS_PROPERTIES_ON_TESTS can be set.
00163 #
00164 # @param [in] ARGN List of arguments for
00165 #                  <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_tests_properties">
00166 #                  set_tests_properties()</a>.
00167 #
00168 # @returns Sets the given properties of the specified test.
00169 #
00170 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_tests_properties
00171 #
00172 # @ingroup CMakeAPI
00173 function (basis_set_tests_properties)
00174   # convert test names to UIDs
00175   set (TEST_UIDS)
00176   list (GET ARGN 0 ARG)
00177   while (ARG AND NOT ARG MATCHES "^PROPERTIES$")
00178     basis_get_test_uid (TEST_UID "${ARG}")
00179     list (APPEND TEST_UIDS "${TEST_UID}")
00180     list (REMOVE_AT ARGN 0)
00181     list (GET ARGN 0 ARG)
00182   endwhile ()
00183   if (NOT ARG MATCHES "^PROPERTIES$")
00184     message (FATAL_ERROR "Missing PROPERTIES argument!")
00185   elseif (NOT TEST_UIDS)
00186     message (FATAL_ERROR "No test specified!")
00187   endif ()
00188   # remove PROPERTIES keyword
00189   list (REMOVE_AT ARGN 0)
00190   # set tests properties
00191   #
00192   # Note: By iterating over the properties, the empty property values
00193   #       are correctly passed on to CMake's set_tests_properties()
00194   #       command, while
00195   #       set_tests_properties(${TEST_UIDS} PROPERTIES ${ARGN})
00196   #       (erroneously) discards the empty elements in ARGN.
00197   if (BASIS_DEBUG)
00198     message ("** basis_set_tests_properties:")
00199     message ("**   Test(s)  :  ${TEST_UIDS}")
00200     message ("**   Properties: [${ARGN}]")
00201   endif ()
00202   list (LENGTH ARGN N)
00203   while (N GREATER 1)
00204     list (GET ARGN 0 PROPERTY)
00205     list (GET ARGN 1 VALUE)
00206     list (REMOVE_AT ARGN 0 1)
00207     list (LENGTH ARGN N)
00208     # The following loop is only required b/c CMake's ARGV and ARGN
00209     # lists do not support arguments which are themselves lists.
00210     # Therefore, we need a way to decide when the list of values for a
00211     # property is terminated. Hence, we only allow known properties
00212     # to be set, except for the first property where the name follows
00213     # directly after the PROPERTIES keyword.
00214     while (N GREATER 0)
00215       list (GET ARGN 0 ARG)
00216       if (ARG MATCHES "${BASIS_PROPERTIES_ON_TESTS_RE}")
00217         break ()
00218       endif ()
00219       list (APPEND VALUE "${ARG}")
00220       list (REMOVE_AT ARGN 0)
00221       list (LENGTH ARGN N)
00222     endwhile ()
00223     # check property name
00224     if ("${PROPERTY}" STREQUAL "")
00225       message (FATAL_ERROR "Empty property name given!")
00226     endif ()
00227     # map test names to test UIDs
00228     if (PROPERTY MATCHES "^DEPENDS$")
00229       set (UIDS)
00230       foreach (V IN LISTS VALUE)
00231         basis_get_test_uid (UID "${V}")
00232         list (APPEND UIDS "${UID}")
00233       endforeach ()
00234       set (VALUE ${UIDS})
00235     endif ()
00236     # set target property
00237     if (BASIS_DEBUG)
00238       message ("**   -> ${PROPERTY} = [${VALUE}]")
00239     endif ()
00240     set_tests_properties (${TEST_UIDS} PROPERTIES ${PROPERTY} "${VALUE}")
00241   endwhile ()
00242   # make sure that every property had a corresponding value
00243   if (NOT N EQUAL 0)
00244     message (FATAL_ERROR "No value given for test property ${ARGN}")
00245   endif ()
00246 endfunction ()
00247 
00248 # ----------------------------------------------------------------------------
00249 ## @brief Get a property of the test.
00250 #
00251 # This function replaces CMake's
00252 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_test_property">
00253 # get_test_property()</a> command.
00254 #
00255 # @param [out] VAR       Property value.
00256 # @param [in]  TEST_NAME Name of test.
00257 # @param [in]  ARGN      Remaining arguments of
00258 #                        <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_test_property">
00259 #                        get_test_property()</a>.
00260 #
00261 # @returns Sets @p VAR to the value of the requested property.
00262 #
00263 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_test_property
00264 #
00265 # @ingroup CMakeAPI
00266 function (basis_get_test_property VAR TEST_NAME)
00267   basis_get_test_uid (TEST_UID "${TEST_NAME}")
00268   get_test_property (VALUE "${TEST_UID}" ${ARGN})
00269   set (${VAR} "${VALUE}" PARENT_SCOPE)
00270 endfunction ()
00271 
00272 # ----------------------------------------------------------------------------
00273 ## @brief Create and add a test driver executable.
00274 #
00275 # @param [in] TESTDRIVER_NAME Name of the test driver.
00276 # @param [in] ARGN            List of source files implementing tests.
00277 #
00278 # @ingroup CMakeAPI
00279 function (basis_add_test_driver TESTDRIVER_NAME)
00280   # parse arguments
00281   CMAKE_PARSE_ARGUMENTS (
00282     ARGN
00283       ""
00284       "EXTRA_INCLUDE;FUNCTION"
00285       ""
00286     ${ARGN}
00287   )
00288   if (ARGN_EXTRA_INCLUDE OR ARGN_FUNCTION)
00289     message (FATAL_ERROR "Invalid argument EXTRA_INCLUDE or FUNCTON! "
00290                          "Use create_test_sourcelist() if you want to create "
00291                          "a custom test driver.")
00292   endif ()
00293   # choose test driver implementation depending on which packages are available
00294   set (TESTDRIVER_INCLUDE "basis/testdriver.h")
00295   set (TESTDRIVER_DEPENDS)
00296   if (ITK_FOUND)
00297     basis_include_directories (BEFORE ${ITK_INCLUDE_DIRS})
00298     set (TESTDRIVER_LINK_DEPENDS ${ITK_LIBRARIES})
00299   endif ()
00300   if (WIN32)
00301     list (APPEND TESTDRIVER_LINK_DEPENDS Ws2_32)
00302   endif ()
00303   # create test driver source code
00304   set (TESTDRIVER_SOURCE "${TESTDRIVER_NAME}")
00305   if (NOT TESTDRIVER_SOURCE MATCHES "\\.cxx")
00306     set (TESTDRIVER_SOURCE "${TESTDRIVER_SOURCE}.cxx")
00307   endif ()
00308   set (CMAKE_TESTDRIVER_BEFORE_TESTMAIN "    #include <basis/testdriver-before-test.inc>")
00309   set (CMAKE_TESTDRIVER_AFTER_TESTMAIN  "    #include <basis/testdriver-after-test.inc>")
00310   create_test_sourcelist (
00311     TESTDRIVER_SOURCES
00312       ${TESTDRIVER_SOURCE} ${ARGN_UNPARSED_ARGUMENTS}
00313       EXTRA_INCLUDE "${TESTDRIVER_INCLUDE}"
00314       FUNCTION      testdriversetup
00315   )
00316   # add test driver executable
00317   basis_add_executable (${TESTDRIVER_NAME} ${TESTDRIVER_SOURCES})
00318   basis_target_link_libraries (${TESTDRIVER_NAME} ${TESTDRIVER_LINK_DEPENDS})
00319   if (ITK_FOUND)
00320     basis_set_target_properties (
00321       ${TESTDRIVER_NAME}
00322       PROPERTIES
00323         COMPILE_DEFINITIONS
00324           TESTDRIVER_NAME=\"${TESTDRIVER_NAME}\"
00325           ITK_VERSION=\"${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}.${ITK_VERSION_PATCH}\"
00326           ITK_VERSION_MAJOR=${ITK_VERSION_MAJOR}
00327     )
00328   else ()
00329     basis_set_target_properties (
00330       ${TESTDRIVER_NAME}
00331       PROPERTIES
00332         COMPILE_DEFINITIONS
00333           TESTDRIVER_NAME=\"${TESTDRIVER_NAME}\"
00334     )
00335   endif ()
00336 endfunction ()
00337 
00338 # ----------------------------------------------------------------------------
00339 ## @brief Add test.
00340 #
00341 # This command is used similar to CMake's
00342 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test">
00343 # add_test()</a> command. It adds a test to the
00344 # <a href="http://www.cmake.org/cmake/help/ctest-2-8-docs.html">CTest</a>-based
00345 # testing system. Unlike CMake's
00346 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test">
00347 # add_test()</a>, this command can, for convenience, implicitly add
00348 # the necessary executable build target to the build system. Therefore,
00349 # instead of the name of the executable command, specify the sources of the
00350 # test implementation. An executable build target is then added by this
00351 # function using basis_add_executable(), and the built executable is used
00352 # as test command. If the @p UNITTEST option is given, the necessary unit
00353 # testing libraries which are part of the BASIS installation are added as
00354 # link dependencies as well as the default implementation of the main()
00355 # function if none of the specified source files has the suffix
00356 # <tt>-main</tt> or <tt>_main</tt> in the file name.
00357 #
00358 # Generator expressions as supported by CMake's
00359 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test">
00360 # add_test()</a> command are also supported by basis_add_test() as arguments of
00361 # the test command. For the argument specifying the test command itself, however,
00362 # only the generator expression $<TARGET_FILE:tgt> is allowed. Alternatively,
00363 # for this special argument, the name of the executable target can be supplied
00364 # directly without the use of the $<TARGET_FILE:tgt> generator expression.
00365 # See documentation of basis_process_generator_expressions() for details on
00366 # the supported generator expressions.
00367 #
00368 # Example:
00369 # @code
00370 # basis_add_test (COMMAND $<TARGET_FILE:basis.testdriver> $<TARGET_FILE:myexe> ...)
00371 # basis_add_test (COMMAND basis.testdriver $<TARGET_FILE:myexe> ...)
00372 # @endcode
00373 #
00374 # @param [in] TEST_NAME Name of the test. If a source file is given
00375 #                       as first argument, the test name is derived
00376 #                       from the name of this source file and the source
00377 #                       file is added to the list of sources which implement
00378 #                       the test command.
00379 # @param [in] ARGN      The following parameters are parsed:
00380 # @par
00381 # <table border="0">
00382 #   <tr>
00383 #     @tp @b COMMAND cmd [arg1 [arg2 ...]] @endtp
00384 #     <td>The command to execute and optionally its arguments. The command
00385 #         can be the name of an executable target (including imported targets),
00386 #         or the name or path of an executable. Alternatively,
00387 #         a test can be build from sources and the build executable
00388 #         used as command. In this case, specify the sources using the
00389 #         @p SOURCES argument. The command name @c cmd if given is used as
00390 #         output name of the built executable. If you do not want to
00391 #         specify the name of the output executable explicitly, but have
00392 #         it derived from the @p TEST_NAME, do not specify the @p COMMAND
00393 #         option and use the @p ARGS option instead to only specify the
00394 #         arguments of the test command.</td>
00395 #   </tr>
00396 #   <tr>
00397 #     @tp @b ARGS arg1 [arg2 ...] @endtp
00398 #     <td>Arguments of the test command. If this option is given, the
00399 #         specified arguments are appended to the arguments specified
00400 #         already as part of the @p COMMAND option, if any.</td>
00401 #   </tr>
00402 #   <tr>
00403 #     @tp @b WORKING_DIRECTORY dir @endtp
00404 #     <td>The working directory of the test command. The generator expression
00405 #         $<TARGET_FILE_DIR:tgt> can be used to specify a working directory
00406 #         which corresponds to the output directory of a given target file.
00407 #         Default: @c TESTING_OUTPUT_DIR / @p TEST_NAME. </td>
00408 #   </tr>
00409 #   <tr>
00410 #     @tp @b CONFIGURATIONS @endtp
00411 #     <td>If a CONFIGURATIONS option is given then the test will be executed
00412 #         only when testing under one of the named configurations.</td>
00413 #   </tr>
00414 #   <tr>
00415 #     @tp @b SOURCES file1 [file2 ...] @endtp
00416 #     <td>The source files of the test. Use the @p UNITTEST option to specify
00417 #         that the sources are an implementation of a unit test. In this case,
00418 #         the default implementation of the main() function is added to the
00419 #         build of the test executable. However, if this list contains a
00420 #         file with the suffix <tt>-main</tt> or <tt>_main</tt> in the name,
00421 #         the default implementation of the main() function is not used.
00422 #         See the documentation of the @p UNITTEST option for further details.</td>
00423 #   </tr>
00424 #   <tr>
00425 #     @tp @b LINK_DEPENDS file1|target1 [file2|target2 ...] @endtp
00426 #     <td>Link dependencies of test executable build from sources.</td>
00427 #   </tr>
00428 #   <tr>
00429 #     @tp @b NO_DEFAULT_MAIN @endtp
00430 #     <td>Force that the implementation of the default main() function
00431 #         is not added to unit tests even if neither of the given source
00432 #         files has the suffix <tt>-main</tt> or <tt>_main</tt> in the
00433 #         file name.</td>
00434 #   </tr>
00435 #   <tr>
00436 #     @tp @b UNITTEST @endtp
00437 #     <td>Specifies that the test is a unit test. In this case, the test
00438 #         implementation is linked to the default unit testing framework
00439 #         for the used programming language which is part of the BASIS
00440 #         installation.</td>
00441 #   </tr>
00442 #   <tr>
00443 #     @tp @b WITH_EXT @endtp
00444 #     <td>Do not strip extension if test name is derived from source file name.</td>
00445 #   </tr>
00446 #   <tr>
00447 #     @tp @b ARGN @endtp
00448 #     <td>All other arguments are passed on to basis_add_executable() if
00449 #         an executable target for the test is added.</td>
00450 #   </tr>
00451 # </table>
00452 #
00453 # @returns Adds build target for test executable if test source files
00454 #          are given and/or adds a CTest test which executes the given
00455 #          test command.
00456 #
00457 # @sa basis_process_generator_expressions()
00458 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test
00459 #
00460 # @todo Make use of ExternalData module to fetch remote test data.
00461 #
00462 # @ingroup CMakeAPI
00463 function (basis_add_test TEST_NAME)
00464   basis_sanitize_for_regex (R "${PROJECT_TESTING_DIR}")
00465   if (NOT CMAKE_CURRENT_SOURCE_DIR MATCHES "^${R}")
00466     message (FATAL_ERROR "Tests can only be added inside ${PROJECT_TESTING_DIR}!")
00467   endif ()
00468 
00469   # --------------------------------------------------------------------------
00470   # parse arguments
00471   CMAKE_PARSE_ARGUMENTS (
00472     ARGN
00473     "UNITTEST;NO_DEFAULT_MAIN;WITH_EXT;CLEAN_WORKING_DIRECTORY_BEFORE_TEST;CLEAN_WORKING_DIRECTORY_AFTER_TEST"
00474     "WORKING_DIRECTORY"
00475     "CONFIGURATIONS;SOURCES;LINK_DEPENDS;COMMAND;ARGS"
00476     ${ARGN}
00477   )
00478 
00479   if (BASIS_DEBUG AND BASIS_VERBOSE)
00480     message ("** basis_add_test():")
00481     message ("**   Test:      ${TEST_NAME}")
00482     message ("**   Command:   ${ARGN_COMMAND}")
00483     message ("**   Arguments: ${ARGN_ARGS}")
00484   endif ()
00485 
00486   list (LENGTH ARGN_COMMAND N)
00487   if (N GREATER 1)
00488     list (GET ARGN_COMMAND 0 CMD)
00489     list (REMOVE_AT ARGN_COMMAND 0)
00490     list (APPEND ARGN_ARGS ${ARGN_COMMAND})
00491     set (ARGN_COMMAND "${CMD}")
00492   endif ()
00493 
00494   # --------------------------------------------------------------------------
00495   # test name
00496   if (NOT ARGN_COMMAND AND NOT ARGN_SOURCES)
00497     get_filename_component (ARGN_SOURCES "${TEST_NAME}" ABSOLUTE)
00498     if (ARGN_WITH_EXT)
00499       basis_get_source_target_name (TEST_NAME "${TEST_NAME}" NAME)
00500       list (APPEND ARGN_UNPARSED_ARGUMENTS WITH_EXT) # pass on to basis_add_executable()
00501     else ()
00502       basis_get_source_target_name (TEST_NAME "${TEST_NAME}" NAME_WE)
00503     endif ()
00504   endif ()
00505 
00506   basis_check_test_name ("${TEST_NAME}")
00507   basis_make_test_uid (TEST_UID "${TEST_NAME}")
00508 
00509   if (BASIS_DEBUG)
00510     message ("** basis_add_test():")
00511     message ("**   Name:      ${TEST_NAME}")
00512     message ("**   Command:   ${ARGN_COMMAND}")
00513     message ("**   Arguments: ${ARGN_ARGS}")
00514     message ("**   Sources:   ${ARGN_SOURCES}")
00515   endif ()
00516 
00517   # --------------------------------------------------------------------------
00518   # build test executable
00519   set (LANGUAGE)
00520   if (ARGN_SOURCES)
00521     if (ARGN_UNITTEST)
00522       basis_get_source_language (LANGUAGE ${ARGN_SOURCES})
00523       if (NOT ARGN_NO_DEFAULT_MAIN)
00524         foreach (SOURCE ${ARGN_SOURCES})
00525           if (SOURCE MATCHES "-main\\.|_main\\.")
00526             set (ARGN_NO_DEFAULT_MAIN 1)
00527             break ()
00528           endif ()
00529         endforeach ()
00530       endif ()
00531       if (LANGUAGE MATCHES "CXX")
00532         if (NOT ARGN_NO_DEFAULT_MAIN)
00533           list (APPEND ARGN_LINK_DEPENDS "${BASIS_TEST_MAIN_LIBRARY}")
00534         endif ()
00535         list (APPEND ARGN_LINK_DEPENDS "${BASIS_TEST_LIBRARY}")
00536         list (APPEND ARGN_LINK_DEPENDS "${CMAKE_THREAD_LIBS_INIT}")
00537       endif ()
00538     endif ()
00539 
00540     basis_add_executable (${TEST_NAME} ${ARGN_SOURCES} ${ARGN_UNPARSED_ARGUMENTS})
00541     if (ARGN_LINK_DEPENDS)
00542       basis_target_link_libraries (${TEST_NAME} ${ARGN_LINK_DEPENDS})
00543     endif ()
00544 
00545     if (ARGN_COMMAND)
00546       basis_set_target_properties (${TEST_NAME} PROPERTIES OUTPUT_NAME ${CMD})
00547     endif ()
00548     set (ARGN_COMMAND ${TEST_NAME})
00549 
00550     if (BASIS_DEBUG)
00551       message ("** Added test executable ${TEST_UID} (${TEST_NAME})")
00552       message ("**   Sources:           ${ARGN_SOURCES}")
00553       message ("**   Link dependencies: ${ARGN_LINK_DEPENDS}")
00554       message ("**   Options:           ${ARGN_UNPARSED_ARGUMENTS}")
00555     endif ()
00556   endif ()
00557 
00558   # --------------------------------------------------------------------------
00559   # add test
00560   message (STATUS "Adding test ${TEST_UID}...")
00561 
00562   if (NOT ARGN_WORKING_DIRECTORY)
00563     set (ARGN_WORKING_DIRECTORY "${TESTING_OUTPUT_DIR}/${TEST_NAME}")
00564   endif ()
00565   if (ARGN_WORKING_DIRECTORY MATCHES "^\\$<(.*):(.*)>$")
00566     if (NOT "${CMAKE_MATCH_1}" STREQUAL "TARGET_FILE_DIR")
00567       message (FATAL_ERROR "Invalid generator expression used for working directory."
00568                            " Only $<TARGET_FILE_DIR:tgt> can be used as argument"
00569                            " of the WORKING_DIRECTORY option.")
00570     endif ()
00571     basis_get_target_location (ARGN_WORKING_DIRECTORY "${CMAKE_MATCH_2}" PATH)
00572   else ()
00573     if (NOT IS_DIRECTORY "${ARGN_WORKING_DIRECTORY}")
00574       file (MAKE_DIRECTORY "${ARGN_WORKING_DIRECTORY}")
00575     endif ()
00576   endif ()
00577   set (OPTS "WORKING_DIRECTORY" "${ARGN_WORKING_DIRECTORY}")
00578   if (ARGN_CONFIGURATIONS)
00579     list (APPEND OPTS "CONFIGURATIONS")
00580     foreach (CONFIG ${ARGN_CONFIGURATIONS})
00581       list (APPEND OPTS "${CONFIG}")
00582     endforeach ()
00583   endif ()
00584 
00585   if (ARGN_COMMAND MATCHES "^\\$<(.*):(.*)>$")
00586     if (NOT "${CMAKE_MATCH_1}" STREQUAL "TARGET_FILE")
00587       message (FATAL_ERROR "Invalid generator expression used for test command."
00588                            " Only $<TARGET_FILE:tgt> can be used as first"
00589                            " argument of the COMMAND option.")
00590     endif ()
00591     basis_get_target_location (ARGN_COMMAND "${CMAKE_MATCH_2}" ABSOLUTE)
00592   else ()
00593     basis_get_target_uid (COMMAND_UID "${ARGN_COMMAND}")
00594     if (TARGET "${COMMAND_UID}")
00595       basis_get_target_location (ARGN_COMMAND "${COMMAND_UID}" ABSOLUTE)
00596     endif ()
00597   endif ()
00598 
00599   basis_process_generator_expressions (ARGN_ARGS ${ARGN_ARGS})
00600 
00601   if (BASIS_DEBUG)
00602     message ("** Add test ${TEST_UID}")
00603     message ("**   Command:    ${ARGN_COMMAND}")
00604     message ("**   Arguments:  ${ARGN_ARGS}")
00605     message ("**   Working in: ${ARGN_WORKING_DIRECTORY}")
00606   endif ()
00607 
00608   add_test (NAME ${TEST_UID} COMMAND ${ARGN_COMMAND} ${ARGN_ARGS} ${OPTS})
00609 
00610   # especially in case of C++ unit tests, if the linkage of the tests is done
00611   # incorrectly, no tests are actually run and the unit test passes
00612   # therefore, add this fail regular expression to identify such issues
00613   set_tests_properties (${TEST_UID} PROPERTIES FAIL_REGULAR_EXPRESSION "(\\[ *PASSED *\\]|Ran) 0 tests|No tests were found!!!")
00614 
00615   message (STATUS "Adding test ${TEST_UID}... - done")
00616 endfunction ()
00617 
00618 # ----------------------------------------------------------------------------
00619 ## @brief Add tests of default options for given executable.
00620 #
00621 # @par Default options:
00622 # <table border="0">
00623 #   <tr>
00624 #     @tp <b>--helpshort</b> @endtp
00625 #     <td>Short help. The output has to match the regular expression
00626 #         "[Uu]sage:\n\s*\<executable name\>", where <executable name>
00627 #         is the name of the tested executable.</td>
00628 #   </tr>
00629 #   <tr>
00630 #     @tp <b>--help, -h</b> @endtp
00631 #     <td>Help screen. Simply tests if the option is accepted.</td>
00632 #   </tr>
00633 #   <tr>
00634 #     @tp <b>--version</b> @endtp
00635 #     <td>Version information. Output has to include the project version string.</td>
00636 #   </tr>
00637 #   <tr>
00638 #     @tp <b>--verbose, -v</b> @endtp
00639 #     <td>Increase verbosity of output messages. Simply tests if the option is accepted.</td>
00640 #   </tr>
00641 # </table>
00642 #
00643 # @param [in] TARGET_NAME Name of executable or script target.
00644 #
00645 # @returns Adds tests for the default options of the specified executable.
00646 function (basis_add_tests_of_default_options TARGET_NAME)
00647   basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
00648 
00649   message (STATUS "Adding tests of default options for ${TARGET_UID}...")
00650 
00651   if (NOT TARGET "${TARGET_UID}")
00652     message (FATAL_ERROR "Unknown target ${TARGET_UID}.")
00653   endif ()
00654 
00655   # get executable name
00656   get_target_property (PREFIX      ${TARGET_UID} "PREFIX")
00657   get_target_property (OUTPUT_NAME ${TARGET_UID} "OUTPUT_NAME")
00658   get_target_property (SUFFIX      ${TARGET_UID} "SUFFIX")
00659 
00660   if (NOT OUTPUT_NAME)
00661     set (EXEC_NAME "${TARGET_UID}")
00662   endif ()
00663   if (PREFIX)
00664     set (EXEC_NAME "${PREFIX}${EXEC_NAME}")
00665   endif ()
00666   if (SUFFIX)
00667     set (EXEC_NAME "${EXEC_NAME}${SUFFIX}")
00668   endif ()
00669 
00670   # get absolute path to executable
00671   get_target_property (EXEC_DIR ${TARGET_UID} "RUNTIME_OUTPUT_DIRECTORY")
00672 
00673   # executable command
00674   set (EXEC_CMD "${EXEC_DIR}/${EXEC_NAME}")
00675 
00676   # test option: -v
00677   basis_add_test (${EXEC}VersionS "${EXEC_CMD}" "-v")
00678 
00679   set_tests_properties (
00680     ${EXEC}VersionS
00681     PROPERTIES
00682       PASS_REGULAR_EXPRESSION "${EXEC} ${PROJECT_VERSION}"
00683   )
00684 
00685   # test option: --version
00686   basis_add_test (${EXEC}VersionL "${EXEC_CMD}" "--version")
00687 
00688   set_tests_properties (
00689     ${EXEC}VersionL
00690     PROPERTIES
00691       PASS_REGULAR_EXPRESSION "${EXEC} ${PROJECT_VERSION}"
00692   )
00693 
00694   # test option: -h
00695   basis_add_test (${EXEC}HelpS "${EXEC_CMD}" "-h")
00696 
00697   # test option: --help
00698   basis_add_test (${EXEC}HelpL "${EXEC_CMD}" "--help")
00699 
00700   # test option: --helpshort
00701   basis_add_test (${EXEC}UsageL "${EXEC_CMD}" "--helpshort")
00702 
00703   set_tests_properties (
00704     ${EXEC}UsageL
00705     PROPERTIES
00706       PASS_REGULAR_EXPRESSION "[Uu]sage:(\n)( )*${EXEC_NAME}"
00707   )
00708 
00709   message (STATUS "Adding tests of default options for ${EXEC}... - done")
00710 endfunction ()
00711 
00712 
00713 ## @}
00714 # end of Doxygen group