#------------------------------------------------------------------------------ # Project Phoenix # # Copyright (c) 2017-2018 RWTH Aachen University, Germany, # Virtual Reality & Immersive Visualization Group. #------------------------------------------------------------------------------ # License # # Licensed under the 3-Clause BSD License (the "License"); # you may not use this file except in compliance with the License. # See the file LICENSE for the full text. # You may obtain a copy of the License at # # https://opensource.org/licenses/BSD-3-Clause # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #------------------------------------------------------------------------------ include(CTest) enable_testing() include(WarningLevels) conan_or_find_package(catch REQUIRED) conan_or_find_package(trompeloeil REQUIRED) define_property(TARGET PROPERTY testing__removes_libraries BRIEF_DOCS "Libraries to be removed for mocking" FULL_DOCS "Libraries to be removed for mocking") define_property(TARGET PROPERTY testing__adds_libraries BRIEF_DOCS "Libraries to be added for mocking" FULL_DOCS "Libraries to be added for mocking") set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY TESTING__AVAILABLE_TESTS "") set(IS_BUILD_SERVER FALSE CACHE BOOL "Is this the build server? So we, e.g., simulate user input for tests requiring it." ) function(CREATE_TEST_MAIN) testing__add_library_(NAME test_main ${ARGV}) endfunction() function(CREATE_MOCK_MAIN) testing__add_library_(NAME mock_main ${ARGV}) endfunction() function(TESTING__ADD_LIBRARY_) set(options) set(oneValueArgs NAME) set(multiValueArgs SOURCES HEADERS INCLUDE_DIRECTORIES LIBRARIES ) cmake_parse_arguments(TESTING__ADD_LIBRARY_ "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) add_library(${TESTING__ADD_LIBRARY__NAME} ${TESTING__ADD_LIBRARY__SOURCES} ${TESTING__ADD_LIBRARY__HEADERS} ) target_include_directories(${TESTING__ADD_LIBRARY__NAME} PUBLIC ${TESTING__ADD_LIBRARY__INCLUDE_DIRECTORIES} ) target_link_libraries(${TESTING__ADD_LIBRARY__NAME} ${TESTING__ADD_LIBRARY__LIBRARIES} ) set_property(TARGET ${TESTING__ADD_LIBRARY__NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) endfunction() function(ADD_TESTS) set(options ) set(oneValueArgs NAME) set(multiValueArgs SOURCES HEADERS INCLUDE_DIRECTORIES LIBRARIES PATH_TO_ADD) cmake_parse_arguments(ADD_TESTS_ "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) foreach(TEST_SOURCE_FILE ${ADD_TESTS__SOURCES}) add_single_test( NAME ${TEST_NAME} SOURCE ${TEST_SOURCE_FILE} INCLUDE_DIRECTORIES ${ADD_TESTS__INCLUDE_DIRECTORIES} LIBRARIES ${ADD_TESTS__LIBRARIES} PATH_TO_ADD ${ADD_TESTS__PATH_TO_ADD} ) endforeach() endfunction() function(ADD_SINGLE_TEST) set(options ) set(oneValueArgs) set(multiValueArgs SOURCE INCLUDE_DIRECTORIES LIBRARIES PATH_TO_ADD) cmake_parse_arguments(ADD_SINGLE_TEST_ "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) get_filename_component( TEST_NAME ${ADD_SINGLE_TEST__SOURCE} NAME_WE) add_executable(${TEST_NAME} ${ADD_SINGLE_TEST__SOURCE} ) target_include_directories(${TEST_NAME} PRIVATE ${ADD_SINGLE_TEST__INCLUDE_DIRECTORIES} ) target_link_libraries(${TEST_NAME} ${ADD_SINGLE_TEST__LIBRARIES} ${CONAN_OR_CMAKE_catch} test_main mock_main ) set_warning_levels_RWTH(${TEST_NAME}) if(IS_BUILD_SERVER) target_compile_definitions(${TEST_NAME} PUBLIC -DIS_BUILD_SERVER) endif() set_property(TARGET ${TEST_NAME} PROPERTY FOLDER "Tests") source_group("Source Files" FILES ${ADD_SINGLE_TEST__SOURCE}) if(ADD_SINGLE_TEST__PATH_TO_ADD AND WIN32 AND MSVC) CONFIGURE_MSVC_USERFILE_(${TEST_NAME} ${ADD_SINGLE_TEST__PATH_TO_ADD}) endif() add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} ) testing__set_timeout_(${TEST_NAME}) set_property(GLOBAL APPEND PROPERTY TESTING__AVAILABLE_TESTS "${TEST_NAME}") endfunction() function(CONFIGURE_MSVC_USERFILE_ TARGET_NAME PATH_TO_ADD) file(TO_NATIVE_PATH "${PATH_TO_ADD}/Release" _DLL_PATH_RELEASE) file(TO_NATIVE_PATH "${PATH_TO_ADD}/Debug" _DLL_PATH_DEBUG) set(SOURCE_USER_FILE "${CMAKE_SOURCE_DIR}/cmake/VisualStudio2013.vcxproj.user.in") set(DESTINATION_USER_FILE "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.vcxproj.user") configure_file(${SOURCE_USER_FILE} ${DESTINATION_USER_FILE} @ONLY) endfunction() function(TESTING__SET_TIMEOUT_ TARGET) if(NOT ${TARGET} MATCHES "integration") set_tests_properties(${TARGET} PROPERTIES TIMEOUT 10.0) else() set_tests_properties(${TARGET} PROPERTIES TIMEOUT 120.0) endif() endfunction() function(ADD_MOCK) set(options ) set(oneValueArgs NAME) set(multiValueArgs SOURCES HEADERS INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES_OF COMPILE_OPTIONS REMOVES_LIBRARIES ADDS_LIBRARIES ) cmake_parse_arguments(ADD_MOCK_ "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) string(TOUPPER ${ADD_MOCK__NAME} ADD_MOCK__NAME_UPPER) string(TOLOWER ${ADD_MOCK__NAME} ADD_MOCK__NAME_LOWER) add_library(${ADD_MOCK__NAME} SHARED ${ADD_MOCK__SOURCES} ${ADD_MOCK__HEADERS} ) target_link_libraries(${ADD_MOCK__NAME} ${CONAN_OR_CMAKE_trompeloeil} mock_main test_main ) foreach(CURRENT_TARGET ${ADD_MOCK__INCLUDE_DIRECTORIES_OF}) get_target_property(CURRENT_INCLUCE_DIRECTORIES ${CURRENT_TARGET} INTERFACE_INCLUDE_DIRECTORIES) if (CURRENT_INCLUCE_DIRECTORIES) target_include_directories(${ADD_MOCK__NAME} PUBLIC ${CURRENT_INCLUCE_DIRECTORIES} ) endif() endforeach() target_include_directories(${ADD_MOCK__NAME} PUBLIC ${ADD_MOCK__INCLUDE_DIRECTORIES} ) target_compile_definitions(${ADD_MOCK__NAME} PRIVATE ${ADD_MOCK__NAME_UPPER}_BUILD ) target_compile_options(${ADD_MOCK__NAME} PUBLIC ${ADD_MOCK__COMPILE_OPTIONS} ) set_property(TARGET ${ADD_MOCK__NAME} PROPERTY FOLDER "Tests/Mocks") set_target_properties(${ADD_MOCK__NAME} PROPERTIES testing__removes_libraries "${ADD_MOCK__REMOVES_LIBRARIES}") set_target_properties(${ADD_MOCK__NAME} PROPERTIES testing__adds_libraries "${ADD_MOCK__ADDS_LIBRARIES}") generate_export_header(${ADD_MOCK__NAME} EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/mocks/${ADD_MOCK__NAME_LOWER}_export.hpp ) set_warning_levels_rwth(${ADD_MOCK__NAME}) endfunction() function(AUTOREMOVE_MOCKED_TEST_SOURCE_FROM) set_property(GLOBAL PROPERTY TESTING__SOURCES__AUTOREMOVE_MOCKED ${ARGN}) endfunction() function(GET_UNMOCKED_TEST_SOURCES test_list) get_property(TEST_SOURCES_LIST GLOBAL PROPERTY TESTING__SOURCES__AUTOREMOVE_MOCKED) set(${test_list} ${TEST_SOURCES_LIST} PARENT_SCOPE) endfunction() function(add_mocked_test cpp_file) set(options ) set(oneValueArgs ) set(multiValueArgs LIBRARIES MOCKING_LIBRARIES_OF MOCKS) cmake_parse_arguments(ADD_MOCKED_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) get_property(TEST_SOURCES_LIST GLOBAL PROPERTY TESTING__SOURCES__AUTOREMOVE_MOCKED) list(REMOVE_ITEM TEST_SOURCES_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/${cpp_file}.cpp) set_property(GLOBAL PROPERTY TESTING__SOURCES__AUTOREMOVE_MOCKED ${TEST_SOURCES_LIST}) set(test_sources src/${cpp_file}.cpp) add_single_test( SOURCE ${test_sources} ) add_dependencies(${cpp_file} ${ADD_MOCKED_TEST_LIBRARIES}) set(LINK_LIBRARIES ) foreach(CURR_TARGET ${ADD_MOCKED_TEST_LIBRARIES}) get_target_property(CURR_LINK_LIBRARIES ${CURR_TARGET} LINK_LIBRARIES) list(APPEND LINK_LIBRARIES ${CURR_LINK_LIBRARIES}) target_link_libraries(${cpp_file} $<TARGET_FILE:${CURR_TARGET}>) get_target_property(CURR_INCLUDE_DIRECTORIES ${CURR_TARGET} INCLUDE_DIRECTORIES) target_include_directories(${cpp_file} PRIVATE ${CURR_INCLUDE_DIRECTORIES}) endforeach() list(REMOVE_DUPLICATES LINK_LIBRARIES) #the libraries themselves must not be in LINK_LIBRARIES foreach(CURR_TARGET ${ADD_MOCKED_TEST_LIBRARIES}) list(REMOVE_ITEM LINK_LIBRARIES ${CURR_TARGET}) endforeach() foreach(MOCK ${ADD_MOCKED_TEST_MOCKS}) get_target_property(LIBRARIES_TO_BE_REMOVED ${MOCK} testing__removes_libraries) foreach(LIBRARY_TO_BE_REMOVED ${LIBRARIES_TO_BE_REMOVED}) list(REMOVE_ITEM LINK_LIBRARIES ${LIBRARY_TO_BE_REMOVED}) endforeach() get_target_property(LIBRARIES_TO_BE_ADDED ${MOCK} testing__adds_libraries) foreach(LIBRARY_TO_BE_ADDED ${LIBRARIES_TO_BE_ADDED}) list(APPEND LINK_LIBRARIES ${LIBRARY_TO_BE_ADDED}) endforeach() target_link_libraries(${cpp_file} ${MOCK}) endforeach() target_link_libraries(${cpp_file} ${CONAN_OR_CMAKE_trompeloeil} ${CONAN_OR_CMAKE_catch} ${LINK_LIBRARIES} ) endfunction() #------------------------------------------------------------------------------- function(CREATE_TEST_SUITES) testing__extract_unit_and_integration_test_targets_() ADD_TEST_SUITE( NAME "Unit-Test-Suite" TEST_REGEX "^test" DEPEND_ON_TARGETS ${TESTING__UNIT_TESTS}) ADD_TEST_SUITE( NAME "Integration-Test-Suite" TEST_REGEX "^integration" DEPEND_ON_TARGETS ${TESTING__INTEGRATION_TESTS}) ADD_TEST_SUITE( NAME "Cpplint-Test-Suite" TEST_REGEX "cpplint") ADD_TEST_SUITE( NAME "Cppcheck-Test-Suite" TEST_REGEX "cppcheck") endfunction() function(ADD_TEST_SUITE) set(options) set(oneValueArgs NAME TEST_REGEX) set(multiValueArgs DEPEND_ON_TARGETS) cmake_parse_arguments(ADD_TEST_SUITE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) #we have to escape the " for visual studio) add_custom_target(${ADD_TEST_SUITE_NAME} COMMAND ctest --tests-regex \"${ADD_TEST_SUITE_TEST_REGEX}\" -C $<CONFIG>) # This comment just ends the escaped signs, for VS highlighting " if(ADD_TEST_SUITE_DEPEND_ON_TARGETS) add_dependencies(${ADD_TEST_SUITE_NAME} ${ADD_TEST_SUITE_DEPEND_ON_TARGETS}) endif() set_property(TARGET ${ADD_TEST_SUITE_NAME} PROPERTY FOLDER "_Test-Suites_") endfunction() function(TESTING__EXTRACT_UNIT_AND_INTEGRATION_TEST_TARGETS_) set(TESTING__INTEGRATION_TESTS ) set(TESTING__UNIT_TESTS ) get_property(TESTING__AVAILABLE_TESTS GLOBAL PROPERTY TESTING__AVAILABLE_TESTS) foreach(CURRENT_TEST ${TESTING__AVAILABLE_TESTS}) if(${CURRENT_TEST} MATCHES "integration_test") list(APPEND TESTING__INTEGRATION_TESTS ${CURRENT_TEST}) else() list(APPEND TESTING__UNIT_TESTS ${CURRENT_TEST}) endif() endforeach() endfunction()