chalk/examples/Unit_Test.cmake

186 lines
7.9 KiB
CMake
Raw Normal View History

2021-09-12 02:40:47 -03:00
"####
# Unit_Test.cmake:
#
# Testing does not properly handle unit test dependencies in some versions of CMake. Therefore,
# we follow a standard workaround from CMake users and create a "check" target used to run the
# tests while rolling-up the dependencies properly. Thus tests may be run using `make check` as
# opposed to the standard CMake call. The CMake test support functions are still used.
#
####
# Bail if not testing
if (NOT CMAKE_BUILD_TYPE STREQUAL "TESTING" )
return()
endif()
set(MEM_TEST_CLI_OPTIONS '--leak-check=full --error-exitcode=100 --show-leak-kinds=all -v')
# Enable testing, setup CTest, etc.
enable_testing()
include( CTest )
add_custom_target(check
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} find . -name "*.gcda" -delete
COMMAND ${CMAKE_CTEST_COMMAND})
add_custom_target(check_leak
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} find . -name "*.gcda" -delete
COMMAND ${CMAKE_CTEST_COMMAND}
--overwrite MemoryCheckCommand=/usr/bin/valgrind
--overwrite MemoryCheckCommandOptions=${MEM_TEST_CLI_OPTIONS}
-T MemCheck)
####
# Function `unit_test_component_autocoder`:
#
# Performs registration of the autocoder step for the generation of GTestBase.hpp, GTestBase.cpp,
# TesterBase.cpp, and TesterBase.hpp. These autocoding steps automate, and keep up-to-date the
# above files saving time.
#
# - **EXE_NAME:** name of exe (unit test exe)
# - **SOURCE_FILES:** source files to provide for autocoding
####
function(unit_test_component_autocoder EXE_NAME SOURCE_FILES INCLUDE_GTEST)
# Search for component xml files
foreach(TEST_SOURCE ${SOURCE_FILES})
string(REGEX MATCH "([./a-zA-Z0-9\-_]+)ComponentAi.xml" COMPONENT_XML ${TEST_SOURCE})
if(NOT ${COMPONENT_XML} STREQUAL "")
# Extract component name
string(REGEX REPLACE "([a-zA-Z0-9\-_]+)(ComponentAi.xml)" "\\1" COMPONENT_NAME ${COMPONENT_XML})
get_filename_component(RAW_XML ${COMPONENT_XML} NAME)
set(AUTOCODE_DIR "${CMAKE_CURRENT_BINARY_DIR}/Autocode")
#TODO: fix once the autocoder does break on build-root
set(TMP_AC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Autocode")
get_module_name("${TMP_AC_DIR}")
set(AC_TMP_MOD "${MODULE_NAME}_clean")
# This creates the temporary Autocoder directory. Since this is used by multiple generations
# it must be created on the fly, and cleaned up afterword. The clean-up step here "generates"
# a fake source
# Add a custom command to make the directory
add_custom_command(
OUTPUT ${TMP_AC_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${TMP_AC_DIR}
)
set(GTEST_SOURCE "${AUTOCODE_DIR}/GTestBase.cpp")
set(BASE_SOURCE "${AUTOCODE_DIR}/TesterBase.cpp")
set(GTEST_HEADER "${AUTOCODE_DIR}/GTestBase.hpp")
set(BASE_HEADER "${AUTOCODE_DIR}/TesterBase.hpp")
target_include_directories(${EXE_NAME} PUBLIC ${AUTOCODE_DIR})
string(REPLACE ";" ":" FPRIME_BUILD_LOCATIONS_SEP "${FPRIME_BUILD_LOCATIONS}")
add_custom_command(
OUTPUT ${GTEST_SOURCE} ${BASE_SOURCE} ${GTEST_HEADER} ${BASE_HEADER}
COMMAND ${CMAKE_COMMAND} -E copy ${TEST_SOURCE} ${TMP_AC_DIR}
COMMAND ${CMAKE_COMMAND} -E chdir ${TMP_AC_DIR} ${CMAKE_COMMAND} -E env pwd
COMMAND ${CMAKE_COMMAND} -E chdir ${TMP_AC_DIR}
${CMAKE_COMMAND} -E env PYTHONPATH=${PYTHON_AUTOCODER_DIR}/src:${PYTHON_AUTOCODER_DIR}/utils BUILD_ROOT="${FPRIME_BUILD_LOCATIONS_SEP}"
FPRIME_AC_CONSTANTS_FILE="${FPRIME_AC_CONSTANTS_FILE}"
PYTHON_AUTOCODER_DIR=${PYTHON_AUTOCODER_DIR} DICTIONARY_DIR=${DICTIONARY_DIR}
${PYTHON_AUTOCODER_DIR}/bin/codegen.py -p ${TMP_AC_DIR} --build_root ${RAW_XML}
COMMAND ${CMAKE_COMMAND} -E chdir ${TMP_AC_DIR}
${CMAKE_COMMAND} -E env PYTHONPATH=${PYTHON_AUTOCODER_DIR}/src:${PYTHON_AUTOCODER_DIR}/utils BUILD_ROOT="${FPRIME_BUILD_LOCATIONS_SEP}"
FPRIME_AC_CONSTANTS_FILE="${FPRIME_AC_CONSTANTS_FILE}"
PYTHON_AUTOCODER_DIR=${PYTHON_AUTOCODER_DIR} DICTIONARY_DIR=${DICTIONARY_DIR}
${PYTHON_AUTOCODER_DIR}/bin/codegen.py -p ${TMP_AC_DIR} --build_root -u ${RAW_XML}
COMMAND ${CMAKE_COMMAND} -E remove ${TMP_AC_DIR}/Tester.hpp ${TMP_AC_DIR}/Tester.cpp
COMMAND ${CMAKE_COMMAND} -E copy_directory ${TMP_AC_DIR} ${AUTOCODE_DIR}
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TMP_AC_DIR}
COMMAND ${CMAKE_COMMAND} -E echo "All done Yo!"
DEPENDS ${TEST_SOURCE} ${TMP_AC_DIR}
)
set_hash_flag("${GTEST_SOURCE}")
set_hash_flag("${BASE_SOURCE}")
# Add autocode sources to module
target_sources(
${EXE_NAME}
PRIVATE
${BASE_SOURCE}
)
if (INCLUDE_GTEST)
target_sources(
${EXE_NAME}
PRIVATE
${GTEST_SOURCE}
)
endif()
endif()
endforeach()
endfunction(unit_test_component_autocoder)
####
# Function `generate_ut`:
#
# Generates the actual unit test, dependencies, and call the autocoder.
#
# - **UT_EXE_NAME:** name of the UT executable to be created
# - **UT_SOURCES_INPUT:** sources to split into source and autocoder file
# - **MOD_DEPS_INPUT:** dependencies split into thread and module dependencies
####
function(generate_ut UT_EXE_NAME UT_SOURCES_INPUT MOD_DEPS_INPUT INCLUDE_GTEST)
# Set the following variables from the existing SOURCE_FILES and LINK_DEPS by splitting them into
# their separate pieces.
#
# AUTOCODER_INPUT_FILES = *.xml and *.txt in SOURCE_FILES_INPUT, fed to auto-coder
# SOURCE_FILES = all other items in SOURCE_FILES_INPUT, set as compile-time sources
# LINK_DEPS = -l link flags given to DEPS_INPUT
# MOD_DEPS = All other module inputs DEPS_INPUT
split_source_files("${UT_SOURCES_INPUT}")
split_dependencies("${MOD_DEPS_INPUT}")
if (NOT DEFINED FPRIME_OBJECT_TYPE)
set(FPRIME_OBJECT_TYPE "Unit-Test")
endif()
generate_executable(${UT_EXE_NAME} "${SOURCE_FILES}" "${MOD_DEPS_INPUT}")
# Generate the UTs w/ autocoding and add the other sources
unit_test_component_autocoder(${UT_EXE_NAME} "${AUTOCODER_INPUT_FILES}" ${INCLUDE_GTEST})
# Link modules
if (INCLUDE_GTEST)
target_link_libraries(
"${UT_EXE_NAME}"
"gtest_main"
"-lpthread" #TODO: fix this
)
endif()
# Add test and dependencies to the "check" target
add_test(NAME ${UT_EXE_NAME} COMMAND ${UT_EXE_NAME})
add_dependencies(check ${UT_EXE_NAME})
add_dependencies(check_leak ${UT_EXE_NAME})
# Check target for this module
# gcda files are generated per object file when executing a binary with coverage enabled
# make sure all existing coverage files are removed before running unit test executables
if (NOT TARGET "${MODULE_NAME}_check")
add_custom_target(
"${MODULE_NAME}_check"
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} find . -name "*.gcda" -delete
COMMAND ${CMAKE_CTEST_COMMAND} --verbose
)
endif()
if (NOT TARGET "${MODULE_NAME}_check_leak")
add_custom_target(
"${MODULE_NAME}_check_leak"
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} find . -name "*.gcda" -delete
COMMAND ${CMAKE_CTEST_COMMAND}
--overwrite MemoryCheckCommand=/usr/bin/valgrind
--overwrite MemoryCheckCommandOptions=${MEM_TEST_CLI_OPTIONS}
--verbose -T MemCheck
)
endif()
# Add top ut wrapper for this module
if (NOT TARGET "${MODULE_NAME}_ut_exe")
add_custom_target("${MODULE_NAME}_ut_exe")
endif()
add_dependencies("${MODULE_NAME}_check" ${UT_EXE_NAME})
add_dependencies("${MODULE_NAME}_check_leak" ${UT_EXE_NAME})
add_dependencies("${MODULE_NAME}_ut_exe" ${UT_EXE_NAME})
# Link library list output on per-module basis
if (CMAKE_DEBUG_OUTPUT)
print_dependencies(${UT_EXE_NAME})
endif()
endfunction()"
import datacloud