1# - Add tests using boost::test 2# 3# Add this line to your test files in place of including a basic boost test header: 4# #include <BoostTestTargetConfig.h> 5# 6# If you cannot do that and must use the included form for a given test, 7# include the line 8# // OVERRIDE_BOOST_TEST_INCLUDED_WARNING 9# in the same file with the boost test include. 10# 11# include(BoostTestTargets) 12# add_boost_test(<testdriver_name> SOURCES <source1> [<more sources...>] 13# [FAIL_REGULAR_EXPRESSION <additional fail regex>] 14# [LAUNCHER <generic launcher script>] 15# [LIBRARIES <library> [<library>...]] 16# [RESOURCES <resource> [<resource>...]] 17# [TESTS <testcasename> [<testcasename>...]]) 18# 19# If for some reason you need access to the executable target created, 20# it can be found in ${${testdriver_name}_TARGET_NAME} as specified when 21# you called add_boost_test 22# 23# Requires CMake 2.6 or newer (uses the 'function' command) 24# 25# Requires: 26# GetForceIncludeDefinitions 27# CopyResourcesToBuildTree 28# 29# Original Author: 30# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net> 31# http://academic.cleardefinition.com 32# Iowa State University HCI Graduate Program/VRAC 33# 34# Copyright Iowa State University 2009-2010. 35# Distributed under the Boost Software License, Version 1.0. 36# (See accompanying file LICENSE_1_0.txt or copy at 37# http://www.boost.org/LICENSE_1_0.txt) 38 39if(__add_boost_test) 40 return() 41endif() 42set(__add_boost_test YES) 43 44set(BOOST_TEST_TARGET_PREFIX "boosttest") 45 46if(NOT Boost_FOUND) 47 find_package(Boost 1.34.0 QUIET) 48endif() 49if("${Boost_VERSION}0" LESS "1034000") 50 set(_shared_msg 51 "NOTE: boost::test-based targets and tests cannot " 52 "be added: boost >= 1.34.0 required but not found. " 53 "(found: '${Boost_VERSION}'; want >=103400) ") 54 if(BUILD_TESTING) 55 message(FATAL_ERROR 56 ${_shared_msg} 57 "You may disable BUILD_TESTING to continue without the " 58 "tests.") 59 else() 60 message(STATUS 61 ${_shared_msg} 62 "BUILD_TESTING disabled, so continuing anyway.") 63 endif() 64endif() 65 66include(GetForceIncludeDefinitions) 67include(CopyResourcesToBuildTree) 68 69if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000") 70 set(_boosttesttargets_libs) 71 set(_boostConfig "BoostTestTargetsIncluded.h") 72 if(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY) 73 find_package(Boost 1.34.0 QUIET COMPONENTS unit_test_framework) 74 endif() 75 if(Boost_UNIT_TEST_FRAMEWORK_LIBRARY) 76 set(_boosttesttargets_libs "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}") 77 if(Boost_USE_STATIC_LIBS) 78 set(_boostConfig "BoostTestTargetsStatic.h") 79 else() 80 if(NOT APPLE) 81 set(_boostConfig "BoostTestTargetsDynamic.h") 82 endif() 83 endif() 84 endif() 85 get_filename_component(_moddir ${CMAKE_CURRENT_LIST_FILE} PATH) 86 configure_file("${_moddir}/${_boostConfig}" 87 "${CMAKE_CURRENT_BINARY_DIR}/BoostTestTargetConfig.h" 88 COPYONLY) 89 include_directories("${CMAKE_CURRENT_BINARY_DIR}") 90endif() 91 92function(add_boost_test _name) 93 if(NOT BUILD_TESTING) 94 return() 95 endif() 96 97 # parse arguments 98 set(_nowhere) 99 set(_curdest _nowhere) 100 set(_val_args 101 SOURCES 102 FAIL_REGULAR_EXPRESSION 103 LAUNCHER 104 LIBRARIES 105 RESOURCES 106 TESTS) 107 set(_bool_args 108 USE_COMPILED_LIBRARY) 109 foreach(_arg ${_val_args} ${_bool_args}) 110 set(${_arg}) 111 endforeach() 112 foreach(_element ${ARGN}) 113 list(FIND _val_args "${_element}" _val_arg_find) 114 list(FIND _bool_args "${_element}" _bool_arg_find) 115 if("${_val_arg_find}" GREATER "-1") 116 set(_curdest "${_element}") 117 elseif("${_bool_arg_find}" GREATER "-1") 118 set("${_element}" ON) 119 set(_curdest _nowhere) 120 else() 121 list(APPEND ${_curdest} "${_element}") 122 endif() 123 endforeach() 124 125 if(_nowhere) 126 message(FATAL_ERROR "Syntax error in use of add_boost_test!") 127 endif() 128 129 if(NOT SOURCES) 130 message(FATAL_ERROR 131 "Syntax error in use of add_boost_test: at least one source file required!") 132 endif() 133 134 if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000") 135 136 include_directories(${Boost_INCLUDE_DIRS}) 137 138 set(includeType) 139 foreach(src ${SOURCES}) 140 file(READ ${src} thefile) 141 if("${thefile}" MATCHES ".*BoostTestTargetConfig.h.*") 142 set(includeType CONFIGURED) 143 set(includeFileLoc ${src}) 144 break() 145 elseif("${thefile}" MATCHES ".*boost/test/included/unit_test.hpp.*") 146 set(includeType INCLUDED) 147 set(includeFileLoc ${src}) 148 set(_boosttesttargets_libs) # clear this out - linking would be a bad idea 149 if(NOT 150 "${thefile}" 151 MATCHES 152 ".*OVERRIDE_BOOST_TEST_INCLUDED_WARNING.*") 153 message("Please replace the include line in ${src} with this alternate include line instead:") 154 message(" \#include <BoostTestTargetConfig.h>") 155 message("Once you've saved your changes, re-run CMake. (See BoostTestTargets.cmake for more info)") 156 endif() 157 break() 158 endif() 159 endforeach() 160 161 if(NOT _boostTestTargetsNagged${_name} STREQUAL "${includeType}") 162 if("includeType" STREQUAL "CONFIGURED") 163 message(STATUS 164 "Test '${_name}' uses the CMake-configurable form of the boost test framework - congrats! (Including File: ${includeFileLoc})") 165 elseif("${includeType}" STREQUAL "INCLUDED") 166 message("In test '${_name}': ${includeFileLoc} uses the 'included' form of the boost unit test framework.") 167 else() 168 message("In test '${_name}': Didn't detect the CMake-configurable boost test include.") 169 message("Please replace your existing boost test include in that test with the following:") 170 message(" \#include <BoostTestTargetConfig.h>") 171 message("Once you've saved your changes, re-run CMake. (See BoostTestTargets.cmake for more info)") 172 endif() 173 endif() 174 set(_boostTestTargetsNagged${_name} 175 "${includeType}" 176 CACHE 177 INTERNAL 178 "" 179 FORCE) 180 181 182 if(RESOURCES) 183 list(APPEND SOURCES ${RESOURCES}) 184 endif() 185 186 # Generate a unique target name, using the relative binary dir 187 # and provided name. (transform all / into _ and remove all other 188 # non-alphabet characters) 189 file(RELATIVE_PATH 190 targetpath 191 "${CMAKE_BINARY_DIR}" 192 "${CMAKE_CURRENT_BINARY_DIR}") 193 string(REGEX REPLACE "[^A-Za-z/_]" "" targetpath "${targetpath}") 194 string(REPLACE "/" "_" targetpath "${targetpath}") 195 196 set(_target_name ${BOOST_TEST_TARGET_PREFIX}-${targetpath}-${_name}) 197 set(${_name}_TARGET_NAME "${_target_name}" PARENT_SCOPE) 198 199 # Build the test. 200 add_executable(${_target_name} ${SOURCES}) 201 202 list(APPEND LIBRARIES ${_boosttesttargets_libs}) 203 204 if(LIBRARIES) 205 target_link_libraries(${_target_name} ${LIBRARIES}) 206 endif() 207 208 if(RESOURCES) 209 set_property(TARGET ${_target_name} PROPERTY RESOURCE ${RESOURCES}) 210 copy_resources_to_build_tree(${_target_name}) 211 endif() 212 213 if(NOT Boost_TEST_FLAGS) 214# set(Boost_TEST_FLAGS --catch_system_error=yes --output_format=XML) 215 set(Boost_TEST_FLAGS --catch_system_error=yes) 216 endif() 217 218 # TODO: Figure out why only recent boost handles individual test running properly 219 220 if(LAUNCHER) 221 set(_test_command ${LAUNCHER} "\$<TARGET_FILE:${_target_name}>") 222 else() 223 set(_test_command ${_target_name}) 224 endif() 225 226 if(TESTS AND ( "${Boost_VERSION}" VERSION_GREATER "103799" )) 227 foreach(_test ${TESTS}) 228 add_test( 229 ${_name}-${_test} 230 ${_test_command} --run_test=${_test} ${Boost_TEST_FLAGS} 231 ) 232 if(FAIL_REGULAR_EXPRESSION) 233 set_tests_properties(${_name}-${_test} 234 PROPERTIES 235 FAIL_REGULAR_EXPRESSION 236 "${FAIL_REGULAR_EXPRESSION}") 237 endif() 238 endforeach() 239 else() 240 add_test( 241 ${_name}-boost_test 242 ${_test_command} ${Boost_TEST_FLAGS} 243 ) 244 if(FAIL_REGULAR_EXPRESSION) 245 set_tests_properties(${_name}-boost_test 246 PROPERTIES 247 FAIL_REGULAR_EXPRESSION 248 "${FAIL_REGULAR_EXPRESSION}") 249 endif() 250 endif() 251 252 # CppCheck the test if we can. 253 if(COMMAND add_cppcheck) 254 add_cppcheck(${_target_name} STYLE UNUSED_FUNCTIONS) 255 endif() 256 257 endif() 258endfunction() 259