Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework CMake test discovery #1673

Merged
merged 8 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,17 @@ jobs:
cpp_version: 17
preset: MSVC
install: true
ctest_args: -C Debug
- name: MSVC 20
os: windows-latest
cpp_version: 20
preset: MSVC
ctest_args: -C Debug
- name: ClangCL
os: windows-latest
cpp_version: 17
preset: ClangCL
ctest_args: -C Debug
- name: Linux Clang 98
os: ubuntu-latest
cpp_version: 98
Expand Down Expand Up @@ -199,7 +202,7 @@ jobs:
- name: Build
run: cmake --build cpputest_build --verbose
- name: Test
run: ctest --test-dir cpputest_build
run: ctest --test-dir cpputest_build ${{ matrix.ctest_args }}

# POST PROCESSING

Expand Down
6 changes: 2 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,10 @@ if(NOT PROJECT_IS_TOP_LEVEL)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE)
endif()

include(CppUTestConfigurationOptions)
include(cmake/gmock.cmake)
if(PROJECT_IS_TOP_LEVEL)
include(CppUTestWarningFlags)
include(cmake/warnings.cmake)
endif()
include(CppUTestBuildTimeDiscoverTests)
include(CppUTestNormalizeTestOutputLocation)
include(GNUInstallDirs)

# Check for symbols before setting a lot of stuff
Expand Down
2 changes: 1 addition & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
{
"name": "arm-embedded",
"inherits": ["defaults"],
"toolchainFile": "${sourceDir}/cmake/arm-none-eabi-gcc.toolchain.cmake",
"toolchainFile": "${sourceDir}/cmake/Toolchains/arm-none-eabi-gcc.toolchain.cmake",
"cacheVariables": {
"CMAKE_CROSSCOMPILING_EMULATOR": "qemu-arm-static;-cpu;cortex-m4"
}
Expand Down
107 changes: 107 additions & 0 deletions cmake/Modules/CppUTest.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
set(_CPPUTEST_DISCOVERY_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/_CppUTestDiscovery.cmake
CACHE INTERNAL "CppUTest discovery scripts"
)

option(CPPUTEST_TESTS_DETAILED "Run discovered tests individually")
option(CPPUTEST_JUNIT_REPORT "Output JUnit test reports")

function(cpputest_discover_tests target)
set(options JUNIT)
set(oneValueArgs DETAILED)
set(multiValueArgs EXTRA_ARGS)
cmake_parse_arguments(
""
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)

# Validate arguments.
if(NOT TARGET ${target})
message(FATAL_ERROR
"Cannot discover tests for target \"${target}\" "
"which is not built by this project."
)
endif()

get_property(target_type
TARGET ${target}
PROPERTY TYPE
)
if(NOT target_type STREQUAL "EXECUTABLE")
message(FATAL_ERROR
"Cannot discover tests for target \"${target}\" "
"which is not an executable."
)
endif()

if(NOT DEFINED _EXTRA_ARGS)
set(_EXTRA_ARGS -v)
endif()

if(NOT DEFINED _DETAILED)
set(_DETAILED ${CPPUTEST_TESTS_DETAILED})
endif()

if(_JUNIT OR CPPUTEST_JUNIT_REPORT)
list(APPEND _EXTRA_ARGS -ojunit)
endif()

set(CTEST_INCLUDE_FILE "${CMAKE_CURRENT_BINARY_DIR}/${target}_include.cmake")
if(CMAKE_CONFIGURATION_TYPES)
set(CTEST_GENERATED_FILE "${CMAKE_CURRENT_BINARY_DIR}/${target}.$<CONFIG>.cmake")
file(WRITE "${CTEST_INCLUDE_FILE}"
"if(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/${target}.\${CTEST_CONFIGURATION_TYPE}.cmake\")\n"
" include(\"${CMAKE_CURRENT_BINARY_DIR}/${target}.\${CTEST_CONFIGURATION_TYPE}.cmake\")\n"
"endif()\n"
)
else()
set(CTEST_GENERATED_FILE "${CMAKE_CURRENT_BINARY_DIR}/${target}.cmake")
file(WRITE "${CTEST_INCLUDE_FILE}"
"if(EXISTS \"${CTEST_GENERATED_FILE}\")\n"
" include(\"${CTEST_GENERATED_FILE}\")\n"
"endif()\n"
)
endif()

add_custom_command(
TARGET ${target} POST_BUILD
BYPRODUCTS "${CTEST_GENERATED_FILE}"
COMMAND
"${CMAKE_COMMAND}"
-D "TESTS_DETAILED:BOOL=${_DETAILED}"
-D "EXECUTABLE=$<TARGET_FILE:${target}>"
-D "EMULATOR=$<TARGET_PROPERTY:${target},CROSSCOMPILING_EMULATOR>"
-D "ARGS=${run_args}"
-D "CTEST_FILE=${CTEST_GENERATED_FILE}"
-P "${_CPPUTEST_DISCOVERY_SCRIPT}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS "${_CPPUTEST_DISCOVERY_SCRIPT}"
VERBATIM
)

if(${CMAKE_VERSION} VERSION_LESS "3.10")
# We can only set one.
get_property(already_set
DIRECTORY
PROPERTY TEST_INCLUDE_FILE
SET
)
if(${already_set})
message(FATAL_ERROR
"Cannot discovery multiple tests from the same file"
)
endif()
set_property(
DIRECTORY
PROPERTY TEST_INCLUDE_FILE "${CTEST_INCLUDE_FILE}"
)
else()
set_property(
DIRECTORY APPEND
PROPERTY TEST_INCLUDE_FILES "${CTEST_INCLUDE_FILE}"
)
endif()

endfunction()
4 changes: 4 additions & 0 deletions cmake/Modules/CppUTestBuildTimeDiscoverTests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ set(_DISCOVER_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/../Scripts/CppUTestBuildTimeDisc

# Create target to discover tests
function (cpputest_buildtime_discover_tests tgt)
Copy link
Contributor Author

@thetic thetic Nov 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose to create a new module rather than refactoring the existing one. Their behavior is not the same. When using cpputest_buildtime_discover_tests with a multi-config project, ctest runs tests regardless of whether and which config it is passed. When using cpputest_discover_tests with such a project, ctest requires a config to be passed. This is the more "normal" behavior that mimics the native add_test command.

I don't know the workflow for breaking changes, but this should be deleted eventually, ideally prior to the next major release.

message(DEPRECATION
"Use cpputest_discover_tests from the CppUTest module instead"
)

set(options)
set(oneValueArgs DETAILED)
set(multiValueArgs)
Expand Down
10 changes: 0 additions & 10 deletions cmake/Modules/CppUTestNormalizeTestOutputLocation.cmake

This file was deleted.

57 changes: 57 additions & 0 deletions cmake/Modules/_CppUTestDiscovery.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
set(script)

function(add_command NAME)
set(_args "")
# use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments
math(EXPR _last_arg ${ARGC}-1)
foreach(_n RANGE 1 ${_last_arg})
set(_arg "${ARGV${_n}}")
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
else()
set(_args "${_args} ${_arg}")
endif()
endforeach()
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
endfunction()

if(NOT EXISTS "${EXECUTABLE}")
message(FATAL_ERROR
"Executable \"${EXECUTABLE}\" does not exist"
)
endif()

if(TESTS_DETAILED)
set(discovery_arg "-ln")
set(select_arg "-st")
else()
set(discovery_arg "-lg")
set(select_arg "-sg")
endif()

execute_process(
COMMAND ${EMULATOR} "${EXECUTABLE}" ${discovery_arg}
OUTPUT_VARIABLE discovered_tests
RESULT_VARIABLE result
ERROR_VARIABLE error
)
if(NOT ${result} EQUAL 0)
message(FATAL_ERROR
"Error executing ${EXECUTABLE}:\n"
"${error}"
)
endif()
separate_arguments(discovered_tests)
foreach(test_name IN LISTS discovered_tests)
add_command(
add_test
"${test_name}"
${EMULATOR}
"${EXECUTABLE}"
${ARGS}
${select_arg}
${test_name}
)
endforeach()

file(WRITE "${CTEST_FILE}" "${script}")
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ set(CMAKE_C_COMPILER "${EW_ROOT_DIR}/bin/iccarm" "${CPU_FLAGS} --dlib_config nor
set(CMAKE_CXX_COMPILER "${EW_ROOT_DIR}/bin/iccarm" "${CPU_FLAGS} --dlib_config normal")
set(CMAKE_ASM_COMPILER "${EW_ROOT_DIR}/bin/iasmarm" "${CPU_FLAGS}")

# Build with cmake -S. -Bbuild -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=cmake/ewarm-linux.toolchain.cmake
# Build with cmake -S. -Bbuild -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ewarm-linux.toolchain.cmake

### END CMAKE_TOOLCHAIN_FILE
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ set(CMAKE_C_COMPILER "${EW_ROOT_DIR}/bin/iccarm.exe" "${CPU_FLAGS} --dlib_config
set(CMAKE_CXX_COMPILER "${EW_ROOT_DIR}/bin/iccarm.exe" "${CPU_FLAGS} --dlib_config normal")
set(CMAKE_ASM_COMPILER "${EW_ROOT_DIR}/bin/iasmarm.exe" "${CPU_FLAGS}")

# Build with cmake -S. -Bbuild -G "NMake Makefiles" -DCMAKE_TOOLCHAIN_FILE=cmake/ewarm-win.toolchain.cmake
# Build with cmake -S. -Bbuild -G "NMake Makefiles" -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ewarm-win.toolchain.cmake

### END CMAKE_TOOLCHAIN_FILE
File renamed without changes.
5 changes: 4 additions & 1 deletion cmake/install.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ install(
DESTINATION "${CPPUTEST_CONFIG_DEST}/Scripts"
)
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/CppUTestBuildTimeDiscoverTests.cmake
FILES
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/CppUTestBuildTimeDiscoverTests.cmake
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/CppUTest.cmake
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/_CppUTestDiscovery.cmake
DESTINATION "${CPPUTEST_CONFIG_DEST}/Modules"
)
configure_package_config_file(CppUTestConfig.cmake.build.in
Expand Down
File renamed without changes.
6 changes: 2 additions & 4 deletions examples/AllTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ target_link_libraries(ExampleTests
CppUTest::CppUTestExt
)

include(CppUTestBuildTimeDiscoverTests)
if(CPPUTEST_TEST_DISCOVERY OR NOT DEFINED CPPUTEST_TEST_DISCOVERY)
cpputest_buildtime_discover_tests(ExampleTests
DETAILED TRUE
)
include(CppUTest)
cpputest_discover_tests(ExampleTests)
endif()
2 changes: 1 addition & 1 deletion scripts/appveyor_ci_build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ switch -Wildcard ($env:Platform)
if ($env:Platform -like 'MinGWClang*')
{
$toolchain_filename = Get-ClangToolchainFilename
$toolchain_path = (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\cmake\$toolchain_filename")
$toolchain_path = (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\cmake\Toolchains\$toolchain_filename")
$toolchain = "-DCMAKE_TOOLCHAIN_FILE=$toolchain_path -DCPPUTEST_WERROR=OFF"
}

Expand Down
6 changes: 3 additions & 3 deletions tests/CppUTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ if(MINGW OR (${CMAKE_HOST_SYSTEM_NAME} MATCHES "OpenBSD"))
endif()
endif()

cpputest_normalize_test_output_location(CppUTestTests)
target_link_libraries(CppUTestTests PRIVATE ${CppUTestLibName})

if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.13")
Expand All @@ -56,6 +55,7 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.13")
)
endif()

if (CPPUTEST_TEST_DISCOVERY)
cpputest_buildtime_discover_tests(CppUTestTests)
if(CPPUTEST_TEST_DISCOVERY)
include(CppUTest)
cpputest_discover_tests(CppUTestTests)
endif()
7 changes: 3 additions & 4 deletions tests/CppUTestExt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ if(MINGW)
endif()
endif()

cpputest_normalize_test_output_location(CppUTestExtTests)
target_link_libraries(CppUTestExtTests
PRIVATE
${CppUTestLibName}
Expand All @@ -53,9 +52,9 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.13")
)
endif()

if (CPPUTEST_TEST_DISCOVERY)
cpputest_buildtime_discover_tests(CppUTestExtTests
# TestOrderedTestMacros must run together
if(CPPUTEST_TEST_DISCOVERY)
include(CppUTest)
cpputest_discover_tests(CppUTestExtTests
DETAILED FALSE
)
endif()