blob: 55be63725efb9df62f13dc36d9117bb1a9c35440 [file] [log] [blame]
Michal Vasko2cd71632021-06-04 12:03:12 +02001# generate test code coverage report
2
3# check that coverage tools are available - always use before GEN_COVERAGE
4macro(GEN_COVERAGE_ENABLE ENABLE_TESTS)
5 # make into normal variable
6 set(TESTS_ENABLED ${ENABLE_TESTS})
7
8 set(GEN_COVERAGE_ENABLED ON)
9 if(NOT TESTS_ENABLED)
10 message(WARNING "You cannot generate coverage when tests are disabled. Enable test by additing parameter -DENABLE_BUILD_TESTS=ON or run cmake with Debug build target.")
11 set(GEN_COVERAGE_ENABLED OFF)
12 endif()
13
14 if(GEN_COVERAGE_ENABLED)
15 find_program(PATH_GCOV NAMES gcov)
16 if(NOT PATH_GCOV)
17 message(WARNING "gcov executable not found! Disabling building code coverage report.")
18 set(GEN_COVERAGE_ENABLED OFF)
19 endif()
20 endif()
21
22 if(GEN_COVERAGE_ENABLED)
23 find_program(PATH_LCOV NAMES lcov)
24 if(NOT PATH_LCOV)
25 message(WARNING "lcov executable not found! Disabling building code coverage report.")
26 set(GEN_COVERAGE_ENABLED OFF)
27 endif()
28 endif()
29
30 if(GEN_COVERAGE_ENABLED)
31 find_program(PATH_GENHTML NAMES genhtml)
32 if(NOT PATH_GENHTML)
33 message(WARNING "genhtml executable not found! Disabling building code coverage report.")
34 set(GEN_COVERAGE_ENABLED OFF)
35 endif()
36 endif()
37
38 if(GEN_COVERAGE_ENABLED)
39 if(NOT CMAKE_COMPILER_IS_GNUCC)
40 message(WARNING "Compiler is not gcc! Coverage may break the tests!")
41 endif()
42
43 execute_process(
44 COMMAND bash "-c" "${CMAKE_C_COMPILER} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\""
45 OUTPUT_VARIABLE GCC_VERSION_FULL
46 OUTPUT_STRIP_TRAILING_WHITESPACE
47 )
48 execute_process(
49 COMMAND bash "-c" "${PATH_GCOV} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\""
50 OUTPUT_VARIABLE GCOV_VERSION_FULL
51 OUTPUT_STRIP_TRAILING_WHITESPACE
52 )
53 if(NOT GCC_VERSION_FULL STREQUAL GCOV_VERSION_FULL)
54 message(WARNING "gcc and gcov versions do not match! Generating coverage may fail with errors.")
55 endif()
56
57 # add specific required compile flags
58 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
59 endif()
60endmacro()
61
62# tests are always expected to be in ${CMAKE_SOURCE_DIR}/tests
63function(GEN_COVERAGE MATCH_TEST_REGEX EXCLUDE_TEST_REGEX)
64 if(NOT GEN_COVERAGE_ENABLED)
65 return()
66 endif()
67
68 # destination
69 set(COVERAGE_DIR "${CMAKE_BINARY_DIR}/code_coverage/")
70 set(COVERAGE_FILE_RAW "${CMAKE_BINARY_DIR}/coverage_raw.info")
71 set(COVERAGE_FILE_CLEAN "${CMAKE_BINARY_DIR}/coverage_clean.info")
72
73 # test match/exclude
74 if(MATCH_TEST_REGEX)
75 set(MATCH_TEST_ARGS -R \"${MATCH_TEST_REGEX}\")
76 endif()
77 if(EXCLUDE_TEST_REGEX)
78 set(EXCLUDE_TEST_ARGS -E \"${EXCLUDE_TEST_REGEX}\")
79 endif()
80
81 # coverage target
82 add_custom_target(coverage
83 COMMENT "Generating code coverage..."
84 WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
85 # Cleanup code counters
86 COMMAND "${PATH_LCOV}" --directory . --zerocounters --quiet
87
88 # Run tests
89 COMMAND "${CMAKE_CTEST_COMMAND}" --quiet ${MATCH_TEST_ARGS} ${EXCLUDE_TEST_ARGS}
90
91 # Capture the counters
92 COMMAND "${PATH_LCOV}"
93 --directory .
94 --rc lcov_branch_coverage=1
95 --rc 'lcov_excl_line=assert'
96 --capture --quiet
97 --output-file "${COVERAGE_FILE_RAW}"
98 # Remove coverage of tests, system headers, etc.
99 COMMAND "${PATH_LCOV}"
100 --remove "${COVERAGE_FILE_RAW}" '${CMAKE_SOURCE_DIR}/tests/*'
101 --rc lcov_branch_coverage=1
102 --quiet --output-file "${COVERAGE_FILE_CLEAN}"
103 # Generate HTML report
104 COMMAND "${PATH_GENHTML}"
105 --branch-coverage --function-coverage --quiet --title "${PROJECT_NAME}"
106 --legend --show-details --output-directory "${COVERAGE_DIR}"
107 "${COVERAGE_FILE_CLEAN}"
108 # Delete the counters
109 COMMAND "${CMAKE_COMMAND}" -E remove
110 ${COVERAGE_FILE_RAW} ${COVERAGE_FILE_CLEAN}
111 )
112
113 add_custom_command(TARGET coverage POST_BUILD
114 WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests"
115 COMMENT "To see the code coverage report, open ${COVERAGE_DIR}index.html"
116 COMMAND ;
117 )
118endfunction()