1# ============================================================================ 2# Copyright (c) 2011-2012 University of Pennsylvania 3# Copyright (c) 2013-2016 Andreas Schuh 4# All rights reserved. 5# 6# See COPYING file for license information or visit 7# https://cmake-basis.github.io/download.html#license 8# ============================================================================ 9 10############################################################################## 11# @file BasisTest.cmake 12# @brief CTest configuration. Include this module instead of CTest. 13# 14# @note This module is included by basis_project_initialize(). 15# 16# @ingroup CMakeAPI 17############################################################################## 18 19# ============================================================================ 20# configuration 21# ============================================================================ 22 23## @brief Request build of tests. 24option (BUILD_TESTING "Request build of tests." OFF) 25 26# include CTest module which enables testing, but prevent it from generating 27# any configuration file or adding targets yet as we want to adjust the 28# default CTest settings--in particular the site name--before 29set (RUN_FROM_DART 1) 30include (CTest) 31 32# mark timeout option as advanced 33mark_as_advanced (DART_TESTING_TIMEOUT) 34 35set (RUN_FROM_CTEST_OR_DART 1) 36include (CTestTargets) 37set (RUN_FROM_CTEST_OR_DART) 38 39# custom CTest configuration 40if (EXISTS "${PROJECT_CONFIG_DIR}/CTestCustom.cmake.in") 41 configure_file ( 42 "${PROJECT_CONFIG_DIR}/CTestCustom.cmake.in" 43 "${PROJECT_BINARY_DIR}/CTestCustom.cmake" 44 @ONLY 45 ) 46elseif (EXISTS "${PROJECT_CONFIG_DIR}/CTestCustom.cmake") 47 configure_file ( 48 "${PROJECT_CONFIG_DIR}/CTestCustom.cmake" 49 "${PROJECT_BINARY_DIR}/CTestCustom.cmake" 50 COPYONLY 51 ) 52else () 53 basis_get_relative_path (CONFIG_DIR "${PROJECT_SOURCE_DIR}" "${PROJECT_CONFIG_DIR}") 54 if (EXISTS "${BASIS_TEMPLATE_DIR}/${CONFIG_DIR}/CTestCustom.cmake.in") 55 # to avoid a Doxygen warning, we need to replace certain patterns used by 56 # the basisproject tool to replace them with project related information 57 # 58 # Note: Do this only on the first pass, otherwise configure_file() will 59 # retrigger CMake every time b/c the modification timestamp of the 60 # source file is newer than the previously configured file. 61 # The use of the "cmake -E copy_if_different" command could be used 62 # here instead, but as we do not expect the CTestCustom.cmake.in 63 # file of the BASIS project template to change, it is sufficient 64 # to only check if we copied the template file already. 65 if (NOT EXISTS "${PROJECT_BINARY_DIR}/CTestCustom.cmake.in") 66 file (READ "${BASIS_TEMPLATE_DIR}/${CONFIG_DIR}/CTestCustom.cmake.in" _TEMPLATE) 67 string (REGEX REPLACE "<year>" "" _TEMPLATE "${_TEMPLATE}") 68 file (WRITE "${PROJECT_BINARY_DIR}/CTestCustom.cmake.in" "${_TEMPLATE}") 69 unset (_TEMPLATE) 70 endif () 71 # configure the modified template file 72 configure_file ( 73 "${PROJECT_BINARY_DIR}/CTestCustom.cmake.in" 74 "${PROJECT_BINARY_DIR}/CTestCustom.cmake" 75 @ONLY 76 ) 77 endif () 78endif () 79 80# ============================================================================ 81# constants 82# ============================================================================ 83 84## @brief Names of recognized properties on tests. 85# 86# Unfortunately, the @c ARGV and @c ARGN arguments of a CMake function() 87# or macro() does not preserve values which themselves are lists. Therefore, 88# it is not possible to distinguish between property names and their values 89# in the arguments passed to basis_set_tests_properties(). 90# To overcome this problem, this list specifies all the possible property names. 91# Everything else is considered to be a property value except the first argument 92# follwing right after the @c PROPERTIES keyword. Alternatively, 93# basis_set_property() can be used as here no disambiguity exists. 94# 95# @note Placeholders such as <CONFIG> are allowed. These are treated 96# as the regular expression "[^ ]+". See basis_list_to_regex(). 97# 98# @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#section_PropertiesonTests 99set (BASIS_PROPERTIES_ON_TESTS 100 ATTACHED_FILES 101 ATTACHED_FILES_ON_FAIL 102 COST 103 DEPENDS 104 ENVIRONMENT 105 FAIL_REGULAR_EXPRESSION 106 LABELS 107 MEASUREMENT 108 PASS_REGULAR_EXPRESSION 109 PROCESSORS 110 REQUIRED_FILES 111 RESOURCE_LOCK 112 RUN_SERIAL 113 TIMEOUT 114 WILL_FAIL 115 WORKING_DIRECTORY 116) 117 118# convert list into regular expression 119basis_list_to_regex (BASIS_PROPERTIES_ON_TESTS_RE ${BASIS_PROPERTIES_ON_TESTS}) 120 121# ============================================================================ 122# utilities 123# ============================================================================ 124 125## @addtogroup CMakeUtilities 126# @{ 127 128 129# ---------------------------------------------------------------------------- 130## @brief Disable testing if project does not implement any tests. 131# 132# This function checks if there are test/ subdirectories in the project and 133# disables and hides the BUILD_TESTING option if none are found. 134function (basis_disable_testing_if_no_tests) 135 if (IS_DIRECTORY "${PROJECT_TESTING_DIR}") 136 set (DISABLE_TESTING FALSE) 137 else () 138 set (DISABLE_TESTING TRUE) 139 endif () 140 if (DISABLE_TESTING) 141 basis_get_relative_path (TESTING_DIR "${PROJECT_SOURCE_DIR}" "${PROJECT_TESTING_DIR}") 142 foreach (M IN LISTS PROJECT_MODULES_ENABLED) 143 if (IS_DIRECTORY "${MODULE_${M}_SOURCE_DIR}/${TESTING_DIR}") 144 set (DISABLE_TESTING FALSE) 145 break () 146 endif () 147 endforeach () 148 endif () 149 if (DISABLE_TESTING) 150 set_property (CACHE BUILD_TESTING PROPERTY VALUE OFF) 151 set_property (CACHE BUILD_TESTING PROPERTY TYPE INTERNAL) 152 else () 153 set_property (CACHE BUILD_TESTING PROPERTY TYPE BOOL) 154 endif () 155endfunction () 156 157# ---------------------------------------------------------------------------- 158## @brief Set a property of the tests. 159# 160# This function replaces CMake's 161# <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_tests_properties"> 162# set_tests_properties()</a> command. 163# 164# @note Due to a bug in CMake (http://www.cmake.org/Bug/view.php?id=12303), 165# except of the first property given directly after the @c PROPERTIES keyword, 166# only properties listed in @c BASIS_PROPERTIES_ON_TESTS can be set. 167# 168# @param [in] ARGN List of arguments for 169# <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_tests_properties"> 170# set_tests_properties()</a>. 171# 172# @returns Sets the given properties of the specified test. 173# 174# @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_tests_properties 175# 176# @ingroup CMakeAPI 177function (basis_set_tests_properties) 178 # convert test names to UIDs 179 set (TEST_UIDS) 180 list (GET ARGN 0 ARG) 181 while (ARG AND NOT ARG MATCHES "^PROPERTIES$") 182 basis_get_test_uid (TEST_UID "${ARG}") 183 list (APPEND TEST_UIDS "${TEST_UID}") 184 list (REMOVE_AT ARGN 0) 185 list (GET ARGN 0 ARG) 186 endwhile () 187 if (NOT ARG MATCHES "^PROPERTIES$") 188 message (FATAL_ERROR "Missing PROPERTIES argument!") 189 elseif (NOT TEST_UIDS) 190 message (FATAL_ERROR "No test specified!") 191 endif () 192 # remove PROPERTIES keyword 193 list (REMOVE_AT ARGN 0) 194 # set tests properties 195 # 196 # Note: By iterating over the properties, the empty property values 197 # are correctly passed on to CMake's set_tests_properties() 198 # command, while 199 # set_tests_properties(${TEST_UIDS} PROPERTIES ${ARGN}) 200 # (erroneously) discards the empty elements in ARGN. 201 if (BASIS_DEBUG) 202 message ("** basis_set_tests_properties:") 203 message ("** Test(s) : ${TEST_UIDS}") 204 message ("** Properties: [${ARGN}]") 205 endif () 206 list (LENGTH ARGN N) 207 while (N GREATER 1) 208 list (GET ARGN 0 PROPERTY) 209 list (GET ARGN 1 VALUE) 210 list (REMOVE_AT ARGN 0 1) 211 list (LENGTH ARGN N) 212 # The following loop is only required b/c CMake's ARGV and ARGN 213 # lists do not support arguments which are themselves lists. 214 # Therefore, we need a way to decide when the list of values for a 215 # property is terminated. Hence, we only allow known properties 216 # to be set, except for the first property where the name follows 217 # directly after the PROPERTIES keyword. 218 while (N GREATER 0) 219 list (GET ARGN 0 ARG) 220 if (ARG MATCHES "${BASIS_PROPERTIES_ON_TESTS_RE}") 221 break () 222 endif () 223 list (APPEND VALUE "${ARG}") 224 list (REMOVE_AT ARGN 0) 225 list (LENGTH ARGN N) 226 endwhile () 227 # check property name 228 if ("${PROPERTY}" STREQUAL "") 229 message (FATAL_ERROR "Empty property name given!") 230 endif () 231 # map test names to test UIDs 232 if (PROPERTY MATCHES "^DEPENDS$") 233 set (UIDS) 234 foreach (V IN LISTS VALUE) 235 basis_get_test_uid (UID "${V}") 236 list (APPEND UIDS "${UID}") 237 endforeach () 238 set (VALUE ${UIDS}) 239 endif () 240 # set target property 241 if (BASIS_DEBUG) 242 message ("** -> ${PROPERTY} = [${VALUE}]") 243 endif () 244 set_tests_properties (${TEST_UIDS} PROPERTIES ${PROPERTY} "${VALUE}") 245 endwhile () 246 # make sure that every property had a corresponding value 247 if (NOT N EQUAL 0) 248 message (FATAL_ERROR "No value given for test property ${ARGN}") 249 endif () 250endfunction () 251 252# ---------------------------------------------------------------------------- 253## @brief Get a property of the test. 254# 255# This function replaces CMake's 256# <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_test_property"> 257# get_test_property()</a> command. 258# 259# @param [out] VAR Property value. 260# @param [in] TEST_NAME Name of test. 261# @param [in] ARGN Remaining arguments of 262# <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_test_property"> 263# get_test_property()</a>. 264# 265# @returns Sets @p VAR to the value of the requested property. 266# 267# @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_test_property 268# 269# @ingroup CMakeAPI 270function (basis_get_test_property VAR TEST_NAME) 271 basis_get_test_uid (TEST_UID "${TEST_NAME}") 272 get_test_property (VALUE "${TEST_UID}" ${ARGN}) 273 set (${VAR} "${VALUE}" PARENT_SCOPE) 274endfunction () 275 276# ---------------------------------------------------------------------------- 277## @brief Create and add a test driver executable. 278# 279# @param [in] TESTDRIVER_NAME Name of the test driver. 280# @param [in] ARGN List of source files implementing tests. 281# 282# @ingroup CMakeAPI 283function (basis_add_test_driver TESTDRIVER_NAME) 284 # parse arguments 285 CMAKE_PARSE_ARGUMENTS ( 286 ARGN 287 "" 288 "EXTRA_INCLUDE;FUNCTION" 289 "" 290 ${ARGN} 291 ) 292 if (ARGN_EXTRA_INCLUDE OR ARGN_FUNCTION) 293 message (FATAL_ERROR "Invalid argument EXTRA_INCLUDE or FUNCTION! " 294 "Use create_test_sourcelist() if you want to create " 295 "a custom test driver.") 296 endif () 297 # choose test driver implementation depending on which packages are available 298 set (TESTDRIVER_INCLUDE "basis/testdriver.h") 299 set (TESTDRIVER_LINK_DEPENDS basis.basis) 300 if (ITK_FOUND) 301 basis_include_directories (BEFORE ${ITK_INCLUDE_DIRS}) 302 list (APPEND TESTDRIVER_LINK_DEPENDS ${ITK_LIBRARIES}) 303 endif () 304 if (WIN32) 305 list (APPEND TESTDRIVER_LINK_DEPENDS Ws2_32) 306 endif () 307 # create test driver source code 308 set (TESTDRIVER_SOURCE "${TESTDRIVER_NAME}") 309 if (NOT TESTDRIVER_SOURCE MATCHES "\\.cxx") 310 set (TESTDRIVER_SOURCE "${TESTDRIVER_SOURCE}.cxx") 311 endif () 312 set (CMAKE_TESTDRIVER_BEFORE_TESTMAIN " #include <basis/testdriver-before-test.inc>") 313 set (CMAKE_TESTDRIVER_AFTER_TESTMAIN " #include <basis/testdriver-after-test.inc>") 314 create_test_sourcelist ( 315 TESTDRIVER_SOURCES 316 ${TESTDRIVER_SOURCE} ${ARGN_UNPARSED_ARGUMENTS} 317 EXTRA_INCLUDE "${TESTDRIVER_INCLUDE}" 318 FUNCTION testdriversetup 319 ) 320 # add test driver executable 321 basis_add_executable (${TESTDRIVER_NAME} ${TESTDRIVER_SOURCES}) 322 basis_target_link_libraries (${TESTDRIVER_NAME} ${TESTDRIVER_LINK_DEPENDS}) 323 if (ITK_FOUND) 324 basis_set_target_properties ( 325 ${TESTDRIVER_NAME} 326 PROPERTIES 327 COMPILE_DEFINITIONS 328 TESTDRIVER_NAME=\"${TESTDRIVER_NAME}\" 329 ITK_VERSION=\"${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}.${ITK_VERSION_PATCH}\" 330 ITK_VERSION_MAJOR=${ITK_VERSION_MAJOR} 331 ) 332 else () 333 basis_set_target_properties ( 334 ${TESTDRIVER_NAME} 335 PROPERTIES 336 COMPILE_DEFINITIONS 337 TESTDRIVER_NAME=\"${TESTDRIVER_NAME}\" 338 ) 339 endif () 340endfunction () 341 342# ---------------------------------------------------------------------------- 343## @brief Add test. 344# 345# This command is used similar to CMake's 346# <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test"> 347# add_test()</a> command. It adds a test to the 348# <a href="http://www.cmake.org/cmake/help/ctest-2-8-docs.html">CTest</a>-based 349# testing system. Unlike CMake's 350# <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test"> 351# add_test()</a>, this command can, for convenience, implicitly add 352# the necessary executable build target to the build system. Therefore, 353# instead of the name of the executable command, specify the sources of the 354# test implementation. An executable build target is then added by this 355# function using basis_add_executable(), and the built executable is used 356# as test command. If the @p UNITTEST option is given, the necessary unit 357# testing libraries which are part of the BASIS installation are added as 358# link dependencies as well as the default implementation of the main() 359# function if none of the specified source files has the suffix 360# <tt>-main</tt> or <tt>_main</tt> in the file name. 361# 362# Generator expressions as supported by CMake's 363# <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test"> 364# add_test()</a> command are also supported by basis_add_test() as arguments of 365# the test command. For the argument specifying the test command itself, however, 366# only the generator expression $<TARGET_FILE:tgt> is allowed. Alternatively, 367# for this special argument, the name of the executable target can be supplied 368# directly without the use of the $<TARGET_FILE:tgt> generator expression. 369# See documentation of basis_process_generator_expressions() for details on 370# the supported generator expressions. 371# 372# Example: 373# @code 374# basis_add_test (COMMAND $<TARGET_FILE:basis.testdriver> $<TARGET_FILE:myexe> ...) 375# basis_add_test (COMMAND basis.testdriver $<TARGET_FILE:myexe> ...) 376# @endcode 377# 378# @param [in] TEST_NAME Name of the test. If a source file is given 379# as first argument, the test name is derived 380# from the name of this source file and the source 381# file is added to the list of sources which implement 382# the test command. 383# @param [in] ARGN The following parameters are parsed: 384# @par 385# <table border="0"> 386# <tr> 387# @tp @b COMMAND cmd [arg1 [arg2 ...]] @endtp 388# <td>The command to execute and optionally its arguments. The command 389# can be the name of an executable target (including imported targets), 390# or the name or path of an executable. Alternatively, 391# a test can be build from sources and the build executable 392# used as command. In this case, specify the sources using the 393# @p SOURCES argument. The command name @c cmd if given is used as 394# output name of the built executable. If you do not want to 395# specify the name of the output executable explicitly, but have 396# it derived from the @p TEST_NAME, do not specify the @p COMMAND 397# option and use the @p ARGS option instead to only specify the 398# arguments of the test command.</td> 399# </tr> 400# <tr> 401# @tp @b ARGS arg1 [arg2 ...] @endtp 402# <td>Arguments of the test command. If this option is given, the 403# specified arguments are appended to the arguments specified 404# already as part of the @p COMMAND option, if any.</td> 405# </tr> 406# <tr> 407# @tp @b WORKING_DIRECTORY dir @endtp 408# <td>The working directory of the test command. The generator expression 409# $<TARGET_FILE_DIR:tgt> can be used to specify a working directory 410# which corresponds to the output directory of a given target file. 411# Default: @c TESTING_OUTPUT_DIR / @p TEST_NAME. </td> 412# </tr> 413# <tr> 414# @tp @b CONFIGURATIONS @endtp 415# <td>If a CONFIGURATIONS option is given then the test will be executed 416# only when testing under one of the named configurations.</td> 417# </tr> 418# <tr> 419# @tp @b SOURCES file1 [file2 ...] @endtp 420# <td>The source files of the test. Use the @p UNITTEST option to specify 421# that the sources are an implementation of a unit test. In this case, 422# the default implementation of the main() function is added to the 423# build of the test executable. However, if this list contains a 424# file with the suffix <tt>-main</tt> or <tt>_main</tt> in the name, 425# the default implementation of the main() function is not used. 426# See the documentation of the @p UNITTEST option for further details.</td> 427# </tr> 428# <tr> 429# @tp @b LINK_DEPENDS file1|target1 [file2|target2 ...] @endtp 430# <td>Link dependencies of test executable build from sources.</td> 431# </tr> 432# <tr> 433# @tp @b NO_DEFAULT_MAIN @endtp 434# <td>Force that the implementation of the default main() function 435# is not added to unit tests even if neither of the given source 436# files has the suffix <tt>-main</tt> or <tt>_main</tt> in the 437# file name.</td> 438# </tr> 439# <tr> 440# @tp @b UNITTEST @endtp 441# <td>Specifies that the test is a unit test. In this case, the test 442# implementation is linked to the default unit testing framework 443# for the used programming language which is part of the BASIS 444# installation.</td> 445# </tr> 446# <tr> 447# @tp @b WITH_EXT @endtp 448# <td>Do not strip extension if test name is derived from source file name.</td> 449# </tr> 450# <tr> 451# @tp @b ARGN @endtp 452# <td>All other arguments are passed on to basis_add_executable() if 453# an executable target for the test is added.</td> 454# </tr> 455# </table> 456# 457# @returns Adds build target for test executable if test source files 458# are given and/or adds a CTest test which executes the given 459# test command. 460# 461# @sa basis_process_generator_expressions() 462# @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test 463# 464# @todo Make use of ExternalData module to fetch remote test data. 465# 466# @ingroup CMakeAPI 467function (basis_add_test TEST_NAME) 468 basis_sanitize_for_regex (R "${PROJECT_TESTING_DIR}") 469 if (NOT CMAKE_CURRENT_SOURCE_DIR MATCHES "^${R}") 470 message (FATAL_ERROR "Tests can only be added inside ${PROJECT_TESTING_DIR}!") 471 endif () 472 473 # -------------------------------------------------------------------------- 474 # parse arguments 475 CMAKE_PARSE_ARGUMENTS ( 476 ARGN 477 "UNITTEST;NO_DEFAULT_MAIN;WITH_EXT;CLEAN_WORKING_DIRECTORY_BEFORE_TEST;CLEAN_WORKING_DIRECTORY_AFTER_TEST" 478 "WORKING_DIRECTORY" 479 "CONFIGURATIONS;SOURCES;LINK_DEPENDS;COMMAND;ARGS" 480 ${ARGN} 481 ) 482 483 if (BASIS_DEBUG AND BASIS_VERBOSE) 484 message ("** basis_add_test():") 485 message ("** Test: ${TEST_NAME}") 486 message ("** Command: ${ARGN_COMMAND}") 487 message ("** Arguments: ${ARGN_ARGS}") 488 endif () 489 490 list (LENGTH ARGN_COMMAND N) 491 if (N GREATER 1) 492 list (GET ARGN_COMMAND 0 CMD) 493 list (REMOVE_AT ARGN_COMMAND 0) 494 list (APPEND ARGN_ARGS ${ARGN_COMMAND}) 495 set (ARGN_COMMAND "${CMD}") 496 endif () 497 498 # -------------------------------------------------------------------------- 499 # test name 500 if (NOT ARGN_COMMAND AND NOT ARGN_SOURCES) 501 get_filename_component (ARGN_SOURCES "${TEST_NAME}" ABSOLUTE) 502 if (ARGN_WITH_EXT) 503 basis_get_source_target_name (TEST_NAME "${TEST_NAME}" NAME) 504 list (APPEND ARGN_UNPARSED_ARGUMENTS WITH_EXT) # pass on to basis_add_executable() 505 else () 506 basis_get_source_target_name (TEST_NAME "${TEST_NAME}" NAME_WE) 507 endif () 508 endif () 509 510 basis_check_test_name ("${TEST_NAME}") 511 basis_make_test_uid (TEST_UID "${TEST_NAME}") 512 513 if (BASIS_DEBUG) 514 message ("** basis_add_test():") 515 message ("** Name: ${TEST_NAME}") 516 message ("** Command: ${ARGN_COMMAND}") 517 message ("** Arguments: ${ARGN_ARGS}") 518 message ("** Sources: ${ARGN_SOURCES}") 519 endif () 520 521 # -------------------------------------------------------------------------- 522 # build test executable 523 set (LANGUAGE) 524 if (ARGN_SOURCES) 525 if (ARGN_UNITTEST) 526 basis_get_source_language (LANGUAGE ${ARGN_SOURCES}) 527 if (NOT ARGN_NO_DEFAULT_MAIN) 528 foreach (SOURCE ${ARGN_SOURCES}) 529 if (SOURCE MATCHES "-main\\.|_main\\.") 530 set (ARGN_NO_DEFAULT_MAIN 1) 531 break () 532 endif () 533 endforeach () 534 endif () 535 if (LANGUAGE MATCHES "CXX") 536 if (NOT ARGN_NO_DEFAULT_MAIN) 537 if (BASIS_TEST_MAIN_LIBRARY) 538 list (APPEND ARGN_LINK_DEPENDS "${BASIS_TEST_MAIN_LIBRARY}") 539 else () 540 message (FATAL_ERROR "Test ${TEST_NAME} added as UNITTEST without NO_DEFAULT_MAIN option," 541 " but BASIS_TEST_MAIN_LIBRARY not set. This library is part of the" 542 " CMake BASIS installation. When you are using the CMake BASIS Modules" 543 " without CMake BASIS installation, add GTest to TEST_DEPENDS and" 544 " set BASIS_TEST_MAIN_LIBRARY to the value of GTEST_MAIN_LIBRARY" 545 " before using the basis_add_test command.") 546 endif () 547 endif () 548 if (BASIS_TEST_LIBRARY) 549 list (APPEND ARGN_LINK_DEPENDS "${BASIS_TEST_LIBRARY}") 550 else () 551 message (FATAL_ERROR "Test ${TEST_NAME} added as UNITTEST, but BASIS_TEST_LIBRARY not set." 552 " This library is part of the CMake BASIS installation. When you are" 553 " using the CMake BASIS Modules without CMake BASIS installation," 554 " add GTest to TEST_DEPENDS and set BASIS_TEST_LIBRARY to the value" 555 " of GTEST_LIBRARY before using the basis_add_test command.") 556 endif () 557 endif () 558 endif () 559 560 basis_add_executable (${TEST_NAME} ${ARGN_SOURCES} ${ARGN_UNPARSED_ARGUMENTS}) 561 if (ARGN_LINK_DEPENDS) 562 basis_target_link_libraries (${TEST_NAME} ${ARGN_LINK_DEPENDS}) 563 endif () 564 565 if (ARGN_COMMAND) 566 basis_set_target_properties (${TEST_NAME} PROPERTIES OUTPUT_NAME ${CMD}) 567 endif () 568 set (ARGN_COMMAND ${TEST_NAME}) 569 570 if (BASIS_DEBUG) 571 message ("** Added test executable ${TEST_UID} (${TEST_NAME})") 572 message ("** Sources: ${ARGN_SOURCES}") 573 message ("** Link dependencies: ${ARGN_LINK_DEPENDS}") 574 message ("** Options: ${ARGN_UNPARSED_ARGUMENTS}") 575 endif () 576 endif () 577 578 # -------------------------------------------------------------------------- 579 # add test 580 message (STATUS "Adding test ${TEST_UID}...") 581 582 if (NOT ARGN_WORKING_DIRECTORY) 583 set (ARGN_WORKING_DIRECTORY "${TESTING_OUTPUT_DIR}/${TEST_NAME}") 584 endif () 585 if (ARGN_WORKING_DIRECTORY MATCHES "^\\$<(.*):(.*)>$") 586 if (NOT "${CMAKE_MATCH_1}" STREQUAL "TARGET_FILE_DIR") 587 message (FATAL_ERROR "Invalid generator expression used for working directory." 588 " Only $<TARGET_FILE_DIR:tgt> can be used as argument" 589 " of the WORKING_DIRECTORY option.") 590 endif () 591 basis_get_target_location (ARGN_WORKING_DIRECTORY "${CMAKE_MATCH_2}" PATH) 592 else () 593 if (NOT IS_DIRECTORY "${ARGN_WORKING_DIRECTORY}") 594 file (MAKE_DIRECTORY "${ARGN_WORKING_DIRECTORY}") 595 endif () 596 endif () 597 set (OPTS "WORKING_DIRECTORY" "${ARGN_WORKING_DIRECTORY}") 598 if (ARGN_CONFIGURATIONS) 599 list (APPEND OPTS "CONFIGURATIONS") 600 foreach (CONFIG ${ARGN_CONFIGURATIONS}) 601 list (APPEND OPTS "${CONFIG}") 602 endforeach () 603 endif () 604 605 if (ARGN_COMMAND MATCHES "^\\$<(.*):(.*)>$") 606 if (NOT "${CMAKE_MATCH_1}" STREQUAL "TARGET_FILE") 607 message (FATAL_ERROR "Invalid generator expression used for test command." 608 " Only $<TARGET_FILE:tgt> can be used as first" 609 " argument of the COMMAND option.") 610 endif () 611 basis_get_target_location (ARGN_COMMAND "${CMAKE_MATCH_2}" ABSOLUTE) 612 else () 613 basis_get_target_uid (COMMAND_UID "${ARGN_COMMAND}") 614 if (TARGET "${COMMAND_UID}") 615 basis_get_target_location (ARGN_COMMAND "${COMMAND_UID}" ABSOLUTE) 616 endif () 617 endif () 618 619 basis_process_generator_expressions (ARGN_ARGS ${ARGN_ARGS}) 620 621 if (BASIS_DEBUG) 622 message ("** Add test ${TEST_UID}") 623 message ("** Command: ${ARGN_COMMAND}") 624 message ("** Arguments: ${ARGN_ARGS}") 625 message ("** Working in: ${ARGN_WORKING_DIRECTORY}") 626 endif () 627 628 add_test (NAME ${TEST_UID} COMMAND ${ARGN_COMMAND} ${ARGN_ARGS} ${OPTS}) 629 630 # especially in case of C++ unit tests, if the linkage of the tests is done 631 # incorrectly, no tests are actually run and the unit test passes 632 # therefore, add this fail regular expression to identify such issues 633 set_tests_properties (${TEST_UID} PROPERTIES FAIL_REGULAR_EXPRESSION "(\\[ *PASSED *\\]|Ran) 0 tests|No tests were found!!!") 634 635 message (STATUS "Adding test ${TEST_UID}... - done") 636endfunction () 637 638# ---------------------------------------------------------------------------- 639## @brief Add tests of default options for given executable. 640# 641# @par Default options: 642# <table border="0"> 643# <tr> 644# @tp <b>--helpshort</b> @endtp 645# <td>Short help. The output has to match the regular expression 646# "[Uu]sage:\n\s*\<executable name\>", where \<executable name\> 647# is the name of the tested executable.</td> 648# </tr> 649# <tr> 650# @tp <b>--help, -h</b> @endtp 651# <td>Help screen. Simply tests if the option is accepted.</td> 652# </tr> 653# <tr> 654# @tp <b>--version</b> @endtp 655# <td>Version information. Output has to include the project version string.</td> 656# </tr> 657# <tr> 658# @tp <b>--verbose, -v</b> @endtp 659# <td>Increase verbosity of output messages. Simply tests if the option is accepted.</td> 660# </tr> 661# </table> 662# 663# @param [in] TARGET_NAME Name of executable or script target. 664# 665# @returns Adds tests for the default options of the specified executable. 666function (basis_add_tests_of_default_options TARGET_NAME) 667 basis_get_target_uid (TARGET_UID "${TARGET_NAME}") 668 669 message (STATUS "Adding tests of default options for ${TARGET_UID}...") 670 671 if (NOT TARGET "${TARGET_UID}") 672 message (FATAL_ERROR "Unknown target ${TARGET_UID}.") 673 endif () 674 675 # get executable name 676 get_target_property (PREFIX ${TARGET_UID} "PREFIX") 677 get_target_property (OUTPUT_NAME ${TARGET_UID} "OUTPUT_NAME") 678 get_target_property (SUFFIX ${TARGET_UID} "SUFFIX") 679 680 if (NOT OUTPUT_NAME) 681 set (EXEC_NAME "${TARGET_UID}") 682 endif () 683 if (PREFIX) 684 set (EXEC_NAME "${PREFIX}${EXEC_NAME}") 685 endif () 686 if (SUFFIX) 687 set (EXEC_NAME "${EXEC_NAME}${SUFFIX}") 688 endif () 689 690 # get absolute path to executable 691 get_target_property (EXEC_DIR ${TARGET_UID} "RUNTIME_OUTPUT_DIRECTORY") 692 693 # executable command 694 set (EXEC_CMD "${EXEC_DIR}/${EXEC_NAME}") 695 696 # test option: -v 697 basis_add_test (${EXEC}VersionS "${EXEC_CMD}" "-v") 698 699 set_tests_properties ( 700 ${EXEC}VersionS 701 PROPERTIES 702 PASS_REGULAR_EXPRESSION "${EXEC} ${PROJECT_VERSION}" 703 ) 704 705 # test option: --version 706 basis_add_test (${EXEC}VersionL "${EXEC_CMD}" "--version") 707 708 set_tests_properties ( 709 ${EXEC}VersionL 710 PROPERTIES 711 PASS_REGULAR_EXPRESSION "${EXEC} ${PROJECT_VERSION}" 712 ) 713 714 # test option: -h 715 basis_add_test (${EXEC}HelpS "${EXEC_CMD}" "-h") 716 717 # test option: --help 718 basis_add_test (${EXEC}HelpL "${EXEC_CMD}" "--help") 719 720 # test option: --helpshort 721 basis_add_test (${EXEC}UsageL "${EXEC_CMD}" "--helpshort") 722 723 set_tests_properties ( 724 ${EXEC}UsageL 725 PROPERTIES 726 PASS_REGULAR_EXPRESSION "[Uu]sage:(\n)( )*${EXEC_NAME}" 727 ) 728 729 message (STATUS "Adding tests of default options for ${EXEC}... - done") 730endfunction () 731 732 733## @} 734# end of Doxygen group 735