123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- set(_json_test_cmake_list_file ${CMAKE_CURRENT_LIST_FILE})
- #############################################################################
- # download test data
- #############################################################################
- include(download_test_data)
- # test fixture to download test data
- add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
- --target download_test_data
- )
- set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA)
- if(JSON_Valgrind)
- find_program(CMAKE_MEMORYCHECK_COMMAND valgrind)
- message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})")
- set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full")
- separate_arguments(memcheck_command)
- endif()
- #############################################################################
- # detect standard support
- #############################################################################
- # C++11 is the minimum required
- set(compiler_supports_cpp_11 TRUE)
- foreach(feature ${CMAKE_CXX_COMPILE_FEATURES})
- if (${feature} STREQUAL cxx_std_14)
- set(compiler_supports_cpp_14 TRUE)
- elseif (${feature} STREQUAL cxx_std_17)
- set(compiler_supports_cpp_17 TRUE)
- elseif (${feature} STREQUAL cxx_std_20)
- set(compiler_supports_cpp_20 TRUE)
- elseif (${feature} STREQUAL cxx_std_23)
- set(compiler_supports_cpp_23 TRUE)
- endif()
- endforeach()
- #############################################################################
- # test functions
- #############################################################################
- #############################################################################
- # json_test_set_test_options(
- # all|<tests>
- # [CXX_STANDARDS all|<args>...]
- # [COMPILE_DEFINITIONS <args>...]
- # [COMPILE_FEATURES <args>...]
- # [COMPILE_OPTIONS <args>...]
- # [LINK_LIBRARIES <args>...]
- # [LINK_OPTIONS <args>...]
- # [TEST_PROPERTIES <args>...])
- #
- # Supply test- and standard-specific build settings and/or test properties.
- # Specify multiple tests using a list e.g., "test-foo;test-bar".
- #
- # Must be called BEFORE the test is created.
- #############################################################################
- function(json_test_set_test_options tests)
- cmake_parse_arguments(args "" ""
- "CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS;TEST_PROPERTIES"
- ${ARGN})
- if(NOT args_CXX_STANDARDS)
- set(args_CXX_STANDARDS "all")
- endif()
- foreach(test ${tests})
- if("${test}" STREQUAL "all")
- set(test "")
- endif()
- foreach(cxx_standard ${args_CXX_STANDARDS})
- if("${cxx_standard}" STREQUAL "all")
- if("${test}" STREQUAL "")
- message(FATAL_ERROR "Not supported. Change defaults in: ${_json_test_cmake_list_file}")
- endif()
- set(test_interface _json_test_interface_${test})
- else()
- set(test_interface _json_test_interface_${test}_cpp_${cxx_standard})
- endif()
- if(NOT TARGET ${test_interface})
- add_library(${test_interface} INTERFACE)
- endif()
- target_compile_definitions(${test_interface} INTERFACE ${args_COMPILE_DEFINITIONS})
- target_compile_features(${test_interface} INTERFACE ${args_COMPILE_FEATURES})
- target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS})
- target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES})
- target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS})
- #set_target_properties(${test_interface} PROPERTIES JSON_TEST_PROPERTIES "${args_TEST_PROPERTIES}")
- set_property(DIRECTORY PROPERTY
- ${test_interface}_TEST_PROPERTIES "${args_TEST_PROPERTIES}"
- )
- endforeach()
- endforeach()
- endfunction()
- # for internal use by _json_test_add_test()
- function(_json_test_apply_test_properties test_target properties_target)
- #get_target_property(test_properties ${properties_target} JSON_TEST_PROPERTIES)
- get_property(test_properties DIRECTORY PROPERTY ${properties_target}_TEST_PROPERTIES)
- if(test_properties)
- set_tests_properties(${test_target} PROPERTIES ${test_properties})
- endif()
- endfunction()
- # for internal use by json_test_add_test_for()
- function(_json_test_add_test test_name file main cxx_standard)
- set(test_target ${test_name}_cpp${cxx_standard})
- if(TARGET ${test_target})
- message(FATAL_ERROR "Target ${test_target} has already been added.")
- endif()
- add_executable(${test_target} ${file})
- target_link_libraries(${test_target} PRIVATE ${main})
- # set and require C++ standard
- set_target_properties(${test_target} PROPERTIES
- CXX_STANDARD ${cxx_standard}
- CXX_STANDARD_REQUIRED ON
- )
- # apply standard-specific build settings
- if(TARGET _json_test_interface__cpp_${cxx_standard})
- target_link_libraries(${test_target} PRIVATE _json_test_interface__cpp_${cxx_standard})
- endif()
- # apply test-specific build settings
- if(TARGET _json_test_interface_${test_name})
- target_link_libraries(${test_target} PRIVATE _json_test_interface_${test_name})
- endif()
- # apply test- and standard-specific build settings
- if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
- target_link_libraries(${test_target} PRIVATE
- _json_test_interface_${test_name}_cpp_${cxx_standard}
- )
- endif()
- if (JSON_FastTests)
- add_test(NAME ${test_target}
- COMMAND ${test_target} ${DOCTEST_TEST_FILTER}
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- )
- else()
- add_test(NAME ${test_target}
- COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- )
- endif()
- set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
- # apply standard-specific test properties
- if(TARGET _json_test_interface__cpp_${cxx_standard})
- _json_test_apply_test_properties(${test_target} _json_test_interface__cpp_${cxx_standard})
- endif()
- # apply test-specific test properties
- if(TARGET _json_test_interface_${test_name})
- _json_test_apply_test_properties(${test_target} _json_test_interface_${test_name})
- endif()
- # apply test- and standard-specific test properties
- if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
- _json_test_apply_test_properties(${test_target}
- _json_test_interface_${test_name}_cpp_${cxx_standard}
- )
- endif()
- if(JSON_Valgrind)
- add_test(NAME ${test_target}_valgrind
- COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER}
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- )
- set_tests_properties(${test_target}_valgrind PROPERTIES
- LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA
- )
- endif()
- endfunction()
- #############################################################################
- # json_test_add_test_for(
- # <file>
- # [NAME <name>]
- # MAIN <main>
- # [CXX_STANDARDS <version_number>...] [FORCE])
- #
- # Given a <file> unit-foo.cpp, produces
- #
- # test-foo_cpp<version_number>
- #
- # if C++ standard <version_number> is supported by the compiler and the
- # source file contains JSON_HAS_CPP_<version_number>.
- # Use NAME <name> to override the filename-derived test name.
- # Use FORCE to create the test regardless of the file containing
- # JSON_HAS_CPP_<version_number>.
- # Test targets are linked against <main>.
- # CXX_STANDARDS defaults to "11".
- #############################################################################
- function(json_test_add_test_for file)
- cmake_parse_arguments(args "FORCE" "MAIN;NAME" "CXX_STANDARDS" ${ARGN})
- if("${args_MAIN}" STREQUAL "")
- message(FATAL_ERROR "Required argument MAIN <main> missing.")
- endif()
- if("${args_NAME}" STREQUAL "")
- get_filename_component(file_basename ${file} NAME_WE)
- string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename})
- else()
- set(test_name ${args_NAME})
- if(NOT test_name MATCHES "test-[^$]+")
- message(FATAL_ERROR "Test name must start with 'test-'.")
- endif()
- endif()
- if("${args_CXX_STANDARDS}" STREQUAL "")
- set(args_CXX_STANDARDS 11)
- endif()
- file(READ ${file} file_content)
- foreach(cxx_standard ${args_CXX_STANDARDS})
- if(NOT compiler_supports_cpp_${cxx_standard})
- continue()
- endif()
- # add unconditionally if C++11 (default) or forced
- if(NOT ("${cxx_standard}" STREQUAL 11 OR args_FORCE))
- string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found)
- if(${has_cpp_found} EQUAL -1)
- continue()
- endif()
- endif()
- _json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard})
- endforeach()
- endfunction()
- #############################################################################
- # json_test_should_build_32bit_test(
- # <build_32bit_var> <build_32bit_only_var> <input>)
- #
- # Check if the 32bit unit test should be built based on the value of <input>
- # and store the result in the variables <build_32bit_var> and
- # <build_32bit_only_var>.
- #############################################################################
- function(json_test_should_build_32bit_test build_32bit_var build_32bit_only_var input)
- set(${build_32bit_only_var} OFF PARENT_SCOPE)
- string(TOUPPER "${input}" ${build_32bit_var})
- if("${${build_32bit_var}}" STREQUAL AUTO)
- # check if compiler is targeting 32bit by default
- include(CheckTypeSize)
- check_type_size("size_t" sizeof_size_t LANGUAGE CXX)
- if(sizeof_size_t AND ${sizeof_size_t} EQUAL 4)
- message(STATUS "Auto-enabling 32bit unit test.")
- set(${build_32bit_var} ON)
- else()
- set(${build_32bit_var} OFF)
- endif()
- elseif("${${build_32bit_var}}" STREQUAL ONLY)
- set(${build_32bit_only_var} ON PARENT_SCOPE)
- endif()
- set(${build_32bit_var} "${${build_32bit_var}}" PARENT_SCOPE)
- endfunction()
|