|
| 1 | +set(_json_test_cmake_list_file ${CMAKE_CURRENT_LIST_FILE}) |
| 2 | + |
| 3 | +############################################################################# |
| 4 | +# download test data |
| 5 | +############################################################################# |
| 6 | + |
| 7 | +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/download_test_data.cmake) |
| 8 | + |
| 9 | +# test fixture to download test data |
| 10 | +add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} |
| 11 | + --target download_test_data |
| 12 | +) |
| 13 | +set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA) |
| 14 | + |
| 15 | +if(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) |
| 20 | +endif() |
| 21 | + |
| 22 | +############################################################################# |
| 23 | +# detect standard support |
| 24 | +############################################################################# |
| 25 | + |
| 26 | +# C++11 is the minimum required |
| 27 | +set(compiler_supports_cpp_11 TRUE) |
| 28 | + |
| 29 | +foreach(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() |
| 39 | +endforeach() |
| 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 | +# |
| 55 | +# Supply test- and standard-specific build settings. |
| 56 | +# Specify multiple tests using a list e.g., "test-foo;test-bar". |
| 57 | +# |
| 58 | +# Must be called BEFORE the test is created. |
| 59 | +############################################################################# |
| 60 | + |
| 61 | +function(json_test_set_test_options tests) |
| 62 | + cmake_parse_arguments(args "" "" |
| 63 | + "CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS" |
| 64 | + ${ARGN}) |
| 65 | + |
| 66 | + if(NOT args_CXX_STANDARDS) |
| 67 | + set(args_CXX_STANDARDS "all") |
| 68 | + endif() |
| 69 | + |
| 70 | + foreach(test ${tests}) |
| 71 | + if("${test}" STREQUAL "all") |
| 72 | + set(test "") |
| 73 | + endif() |
| 74 | + |
| 75 | + foreach(cxx_standard ${args_CXX_STANDARDS}) |
| 76 | + if("${cxx_standard}" STREQUAL "all") |
| 77 | + if("${test}" STREQUAL "") |
| 78 | + message(FATAL_ERROR "Not supported. Change defaults in: ${_json_test_cmake_list_file}") |
| 79 | + endif() |
| 80 | + set(test_interface _json_test_interface_${test}) |
| 81 | + else() |
| 82 | + set(test_interface _json_test_interface_${test}_cpp_${cxx_standard}) |
| 83 | + endif() |
| 84 | + |
| 85 | + if(NOT TARGET ${test_interface}) |
| 86 | + add_library(${test_interface} INTERFACE) |
| 87 | + endif() |
| 88 | + |
| 89 | + target_compile_definitions(${test_interface} INTERFACE ${args_COMPILE_DEFINITIONS}) |
| 90 | + target_compile_features(${test_interface} INTERFACE ${args_COMPILE_FEATURES}) |
| 91 | + target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS}) |
| 92 | + target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES}) |
| 93 | + target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS}) |
| 94 | + endforeach() |
| 95 | + endforeach() |
| 96 | +endfunction() |
| 97 | + |
| 98 | +# for internal use by json_test_add_test_for() |
| 99 | +function(_json_test_add_test test_name file main cxx_standard) |
| 100 | + set(test_target ${test_name}_cpp${cxx_standard}) |
| 101 | + |
| 102 | + if(TARGET ${test_target}) |
| 103 | + message(FATAL_ERROR "Target ${test_target} has already been added.") |
| 104 | + endif() |
| 105 | + |
| 106 | + add_executable(${test_target} ${file}) |
| 107 | + target_link_libraries(${test_target} PRIVATE ${main}) |
| 108 | + |
| 109 | + # set and require C++ standard |
| 110 | + set_target_properties(${test_target} PROPERTIES |
| 111 | + CXX_STANDARD ${cxx_standard} |
| 112 | + CXX_STANDARD_REQUIRED ON |
| 113 | + ) |
| 114 | + |
| 115 | + # apply standard-specific build settings |
| 116 | + if(TARGET _json_test_interface_""_cpp_${cxx_standard}) |
| 117 | + target_link_libraries(${testcase_target} PRIVATE _json_test_interface_""_cpp_${cxx_standard}) |
| 118 | + endif() |
| 119 | + |
| 120 | + # apply test-specific build settings |
| 121 | + if(TARGET _json_test_interface_${test_name}) |
| 122 | + target_link_libraries(${test_target} PRIVATE _json_test_interface_${test_name}) |
| 123 | + endif() |
| 124 | + |
| 125 | + # apply test- and standard-specific build settings |
| 126 | + if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard}) |
| 127 | + target_link_libraries(${test_target} PRIVATE |
| 128 | + _json_test_interface_${test_name}_cpp_${cxx_standard} |
| 129 | + ) |
| 130 | + endif() |
| 131 | + |
| 132 | + if (JSON_FastTests) |
| 133 | + add_test(NAME ${test_target} |
| 134 | + COMMAND ${test_target} ${DOCTEST_TEST_FILTER} |
| 135 | + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} |
| 136 | + ) |
| 137 | + else() |
| 138 | + add_test(NAME ${test_target} |
| 139 | + COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip |
| 140 | + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} |
| 141 | + ) |
| 142 | + endif() |
| 143 | + set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA) |
| 144 | + |
| 145 | + if(JSON_Valgrind) |
| 146 | + add_test(NAME ${test_target}_valgrind |
| 147 | + COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER} |
| 148 | + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} |
| 149 | + ) |
| 150 | + set_tests_properties(${test_target}_valgrind PROPERTIES |
| 151 | + LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA |
| 152 | + ) |
| 153 | + endif() |
| 154 | +endfunction() |
| 155 | + |
| 156 | +############################################################################# |
| 157 | +# json_test_add_test_for( |
| 158 | +# <file> |
| 159 | +# MAIN <main> |
| 160 | +# [CXX_STANDARDS <version_number>...] [FORCE]) |
| 161 | +# |
| 162 | +# Given a <file> unit-foo.cpp, produces |
| 163 | +# |
| 164 | +# test-foo_cpp<version_number> |
| 165 | +# |
| 166 | +# if C++ standard <version_number> is supported by the compiler and the |
| 167 | +# source file contains JSON_HAS_CPP_<version_number>. |
| 168 | +# Use FORCE to create the test regardless of the file containing |
| 169 | +# JSON_HAS_CPP_<version_number>. |
| 170 | +# Test targets are linked against <main>. |
| 171 | +# CXX_STANDARDS defaults to "11". |
| 172 | +############################################################################# |
| 173 | + |
| 174 | +function(json_test_add_test_for file) |
| 175 | + cmake_parse_arguments(args "FORCE" "MAIN" "CXX_STANDARDS" ${ARGN}) |
| 176 | + |
| 177 | + get_filename_component(file_basename ${file} NAME_WE) |
| 178 | + string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename}) |
| 179 | + |
| 180 | + if("${args_MAIN}" STREQUAL "") |
| 181 | + message(FATAL_ERROR "Required argument MAIN <main> missing.") |
| 182 | + endif() |
| 183 | + |
| 184 | + if("${args_CXX_STANDARDS}" STREQUAL "") |
| 185 | + set(args_CXX_STANDARDS 11) |
| 186 | + endif() |
| 187 | + |
| 188 | + file(READ ${file} file_content) |
| 189 | + foreach(cxx_standard ${args_CXX_STANDARDS}) |
| 190 | + if(NOT compiler_supports_cpp_${cxx_standard}) |
| 191 | + continue() |
| 192 | + endif() |
| 193 | + |
| 194 | + # add unconditionally if C++11 (default) or forced |
| 195 | + if(NOT ("${cxx_standard}" STREQUAL 11 OR args_FORCE)) |
| 196 | + string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found) |
| 197 | + if(${has_cpp_found} EQUAL -1) |
| 198 | + continue() |
| 199 | + endif() |
| 200 | + endif() |
| 201 | + |
| 202 | + _json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard}) |
| 203 | + endforeach() |
| 204 | +endfunction() |
0 commit comments