1set(_json_test_cmake_list_file ${CMAKE_CURRENT_LIST_FILE}) 2 3############################################################################# 4# download test data 5############################################################################# 6 7include(download_test_data) 8 9# test fixture to download test data 10add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} 11 --target download_test_data 12) 13set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA) 14 15if(JSON_Valgrind) 16 find_program(CMAKE_MEMORYCHECK_COMMAND valgrind) 17 message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})") 18 set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full") 19 separate_arguments(memcheck_command) 20endif() 21 22############################################################################# 23# detect standard support 24############################################################################# 25 26# C++11 is the minimum required 27set(compiler_supports_cpp_11 TRUE) 28 29foreach(feature ${CMAKE_CXX_COMPILE_FEATURES}) 30 if (${feature} STREQUAL cxx_std_14) 31 set(compiler_supports_cpp_14 TRUE) 32 elseif (${feature} STREQUAL cxx_std_17) 33 set(compiler_supports_cpp_17 TRUE) 34 elseif (${feature} STREQUAL cxx_std_20) 35 set(compiler_supports_cpp_20 TRUE) 36 elseif (${feature} STREQUAL cxx_std_23) 37 set(compiler_supports_cpp_23 TRUE) 38 endif() 39endforeach() 40 41############################################################################# 42# test functions 43############################################################################# 44 45############################################################################# 46# json_test_set_test_options( 47# all|<tests> 48# [CXX_STANDARDS all|<args>...] 49# [COMPILE_DEFINITIONS <args>...] 50# [COMPILE_FEATURES <args>...] 51# [COMPILE_OPTIONS <args>...] 52# [LINK_LIBRARIES <args>...] 53# [LINK_OPTIONS <args>...] 54# [TEST_PROPERTIES <args>...]) 55# 56# Supply test- and standard-specific build settings and/or test properties. 57# Specify multiple tests using a list e.g., "test-foo;test-bar". 58# 59# Must be called BEFORE the test is created. 60############################################################################# 61 62function(json_test_set_test_options tests) 63 cmake_parse_arguments(args "" "" 64 "CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS;TEST_PROPERTIES" 65 ${ARGN}) 66 67 if(NOT args_CXX_STANDARDS) 68 set(args_CXX_STANDARDS "all") 69 endif() 70 71 foreach(test ${tests}) 72 if("${test}" STREQUAL "all") 73 set(test "") 74 endif() 75 76 foreach(cxx_standard ${args_CXX_STANDARDS}) 77 if("${cxx_standard}" STREQUAL "all") 78 if("${test}" STREQUAL "") 79 message(FATAL_ERROR "Not supported. Change defaults in: ${_json_test_cmake_list_file}") 80 endif() 81 set(test_interface _json_test_interface_${test}) 82 else() 83 set(test_interface _json_test_interface_${test}_cpp_${cxx_standard}) 84 endif() 85 86 if(NOT TARGET ${test_interface}) 87 add_library(${test_interface} INTERFACE) 88 endif() 89 90 target_compile_definitions(${test_interface} INTERFACE ${args_COMPILE_DEFINITIONS}) 91 target_compile_features(${test_interface} INTERFACE ${args_COMPILE_FEATURES}) 92 target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS}) 93 target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES}) 94 target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS}) 95 #set_target_properties(${test_interface} PROPERTIES JSON_TEST_PROPERTIES "${args_TEST_PROPERTIES}") 96 set_property(DIRECTORY PROPERTY 97 ${test_interface}_TEST_PROPERTIES "${args_TEST_PROPERTIES}" 98 ) 99 endforeach() 100 endforeach() 101endfunction() 102 103# for internal use by _json_test_add_test() 104function(_json_test_apply_test_properties test_target properties_target) 105 #get_target_property(test_properties ${properties_target} JSON_TEST_PROPERTIES) 106 get_property(test_properties DIRECTORY PROPERTY ${properties_target}_TEST_PROPERTIES) 107 if(test_properties) 108 set_tests_properties(${test_target} PROPERTIES ${test_properties}) 109 endif() 110endfunction() 111 112# for internal use by json_test_add_test_for() 113function(_json_test_add_test test_name file main cxx_standard) 114 set(test_target ${test_name}_cpp${cxx_standard}) 115 116 if(TARGET ${test_target}) 117 message(FATAL_ERROR "Target ${test_target} has already been added.") 118 endif() 119 120 add_executable(${test_target} ${file}) 121 target_link_libraries(${test_target} PRIVATE ${main}) 122 123 # set and require C++ standard 124 set_target_properties(${test_target} PROPERTIES 125 CXX_STANDARD ${cxx_standard} 126 CXX_STANDARD_REQUIRED ON 127 ) 128 129 # apply standard-specific build settings 130 if(TARGET _json_test_interface__cpp_${cxx_standard}) 131 target_link_libraries(${test_target} PRIVATE _json_test_interface__cpp_${cxx_standard}) 132 endif() 133 134 # apply test-specific build settings 135 if(TARGET _json_test_interface_${test_name}) 136 target_link_libraries(${test_target} PRIVATE _json_test_interface_${test_name}) 137 endif() 138 139 # apply test- and standard-specific build settings 140 if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard}) 141 target_link_libraries(${test_target} PRIVATE 142 _json_test_interface_${test_name}_cpp_${cxx_standard} 143 ) 144 endif() 145 146 if (JSON_FastTests) 147 add_test(NAME ${test_target} 148 COMMAND ${test_target} ${DOCTEST_TEST_FILTER} 149 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 150 ) 151 else() 152 add_test(NAME ${test_target} 153 COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip 154 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 155 ) 156 endif() 157 set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA) 158 159 # apply standard-specific test properties 160 if(TARGET _json_test_interface__cpp_${cxx_standard}) 161 _json_test_apply_test_properties(${test_target} _json_test_interface__cpp_${cxx_standard}) 162 endif() 163 164 # apply test-specific test properties 165 if(TARGET _json_test_interface_${test_name}) 166 _json_test_apply_test_properties(${test_target} _json_test_interface_${test_name}) 167 endif() 168 169 # apply test- and standard-specific test properties 170 if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard}) 171 _json_test_apply_test_properties(${test_target} 172 _json_test_interface_${test_name}_cpp_${cxx_standard} 173 ) 174 endif() 175 176 if(JSON_Valgrind) 177 add_test(NAME ${test_target}_valgrind 178 COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER} 179 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 180 ) 181 set_tests_properties(${test_target}_valgrind PROPERTIES 182 LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA 183 ) 184 endif() 185endfunction() 186 187############################################################################# 188# json_test_add_test_for( 189# <file> 190# [NAME <name>] 191# MAIN <main> 192# [CXX_STANDARDS <version_number>...] [FORCE]) 193# 194# Given a <file> unit-foo.cpp, produces 195# 196# test-foo_cpp<version_number> 197# 198# if C++ standard <version_number> is supported by the compiler and the 199# source file contains JSON_HAS_CPP_<version_number>. 200# Use NAME <name> to override the filename-derived test name. 201# Use FORCE to create the test regardless of the file containing 202# JSON_HAS_CPP_<version_number>. 203# Test targets are linked against <main>. 204# CXX_STANDARDS defaults to "11". 205############################################################################# 206 207function(json_test_add_test_for file) 208 cmake_parse_arguments(args "FORCE" "MAIN;NAME" "CXX_STANDARDS" ${ARGN}) 209 210 if("${args_MAIN}" STREQUAL "") 211 message(FATAL_ERROR "Required argument MAIN <main> missing.") 212 endif() 213 214 if("${args_NAME}" STREQUAL "") 215 get_filename_component(file_basename ${file} NAME_WE) 216 string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename}) 217 else() 218 set(test_name ${args_NAME}) 219 if(NOT test_name MATCHES "test-[^$]+") 220 message(FATAL_ERROR "Test name must start with 'test-'.") 221 endif() 222 endif() 223 224 if("${args_CXX_STANDARDS}" STREQUAL "") 225 set(args_CXX_STANDARDS 11) 226 endif() 227 228 file(READ ${file} file_content) 229 foreach(cxx_standard ${args_CXX_STANDARDS}) 230 if(NOT compiler_supports_cpp_${cxx_standard}) 231 continue() 232 endif() 233 234 # add unconditionally if C++11 (default) or forced 235 if(NOT ("${cxx_standard}" STREQUAL 11 OR args_FORCE)) 236 string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found) 237 if(${has_cpp_found} EQUAL -1) 238 continue() 239 endif() 240 endif() 241 242 _json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard}) 243 endforeach() 244endfunction() 245 246############################################################################# 247# json_test_should_build_32bit_test( 248# <build_32bit_var> <build_32bit_only_var> <input>) 249# 250# Check if the 32bit unit test should be built based on the value of <input> 251# and store the result in the variables <build_32bit_var> and 252# <build_32bit_only_var>. 253############################################################################# 254 255function(json_test_should_build_32bit_test build_32bit_var build_32bit_only_var input) 256 set(${build_32bit_only_var} OFF PARENT_SCOPE) 257 string(TOUPPER "${input}" ${build_32bit_var}) 258 if("${${build_32bit_var}}" STREQUAL AUTO) 259 # check if compiler is targeting 32bit by default 260 include(CheckTypeSize) 261 check_type_size("size_t" sizeof_size_t LANGUAGE CXX) 262 if(sizeof_size_t AND ${sizeof_size_t} EQUAL 4) 263 message(STATUS "Auto-enabling 32bit unit test.") 264 set(${build_32bit_var} ON) 265 else() 266 set(${build_32bit_var} OFF) 267 endif() 268 elseif("${${build_32bit_var}}" STREQUAL ONLY) 269 set(${build_32bit_only_var} ON PARENT_SCOPE) 270 endif() 271 272 set(${build_32bit_var} "${${build_32bit_var}}" PARENT_SCOPE) 273endfunction() 274