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