• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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