Skip to content

Commit cda535f

Browse files
committed
Switch to xml report
1 parent 2ff1fc0 commit cda535f

File tree

3 files changed

+133
-136
lines changed

3 files changed

+133
-136
lines changed

.github/workflows/nix.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ jobs:
169169
- linux
170170
compiler:
171171
- gcc
172-
- clang
173172
configuration:
174173
- Debug
175174
needs: dependencies
@@ -209,10 +208,11 @@ jobs:
209208
with:
210209
generator: Ninja
211210
configuration: ${{ matrix.configuration }}
211+
cmake-args: '-DCODE_COVERAGE_REPORT_FORMAT=xml'
212212
cmake-target: coverage_report
213213
- name: archive coverage results
214214
uses: actions/upload-artifact@v3
215215
with:
216-
name: code-coverage-report
217-
path: coverage_report/**
216+
name: coverage-report.xml
217+
path: .build/coverage_report.xml
218218
retention-days: 30

Builds/CMake/CodeCoverage.cmake

+121-129
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@
5959
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
6060
# Example:
6161
# set(COVERAGE_EXCLUDES "dir1/*")
62-
# setup_target_for_coverage_gcovr_html(
62+
# setup_target_for_coverage_gcovr(
6363
# NAME coverage
6464
# EXECUTABLE testrunner
65+
# FORMAT html-details
6566
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
6667
# EXCLUDE "dir2/*")
6768
#
@@ -95,7 +96,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
9596
find_program( LLVMCOV_PATH llvm-cov )
9697
endif()
9798
if (NOT LLVMCOV_PATH)
98-
message(FATAL_ERROR "llvm-cov tool not found! Aborting...")
99+
message(FATAL_ERROR "Could not find llvm-cov tool! Aborting...")
99100
endif()
100101
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
101102
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
@@ -104,7 +105,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
104105
endif()
105106

106107
if(NOT GCOV_TOOL)
107-
message(FATAL_ERROR "gcov tool not found! Aborting...")
108+
message(FATAL_ERROR "Could not find gcov or llvm-cov tool! Aborting...")
108109
endif() # NOT GCOV_TOOL
109110

110111
# Check supported compiler (Clang, GNU and Flang)
@@ -176,26 +177,35 @@ endif()
176177
# NOTE! The executable should always have a ZERO as exit code otherwise
177178
# the coverage generation will not complete.
178179
#
179-
# setup_target_for_coverage_gcovr_xml(
180+
# setup_target_for_coverage_gcovr(
180181
# NAME ctest_coverage # New target name
181182
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
182183
# DEPENDENCIES executable_target # Dependencies to build first
183184
# BASE_DIRECTORY "../" # Base directory for report
184185
# # (defaults to PROJECT_SOURCE_DIR)
186+
# FORMAT "cobertura" # Output format, one of:
187+
# # xml cobertura sonarqube json-summary
188+
# # json-details coveralls csv txt
189+
# # html-single html-nested html-details
190+
# # (xml is an alias to cobertura;
191+
# # if no format is set, defaults to xml;
192+
# # if any of the supported formats is
193+
# # set in GCOVR_ADDITIONAL_ARGS options
194+
# # it will always take priority)
185195
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
186196
# # to BASE_DIRECTORY, with CMake 3.4+)
187197
# )
188198
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
189199
# GCVOR command.
190-
function(setup_target_for_coverage_gcovr_xml)
200+
function(setup_target_for_coverage_gcovr)
191201
set(options NONE)
192-
set(oneValueArgs BASE_DIRECTORY NAME)
202+
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
193203
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
194204
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
195205

196206
if(NOT GCOVR_PATH)
197-
message(FATAL_ERROR "gcovr not found! Aborting...")
198-
endif() # NOT GCOVR_PATH
207+
message(FATAL_ERROR "Could not find gcovr tool! Aborting...")
208+
endif()
199209

200210
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
201211
if(DEFINED Coverage_BASE_DIRECTORY)
@@ -204,109 +214,87 @@ function(setup_target_for_coverage_gcovr_xml)
204214
set(BASEDIR ${PROJECT_SOURCE_DIR})
205215
endif()
206216

207-
# Collect excludes (CMake 3.4+: Also compute absolute paths)
208-
set(GCOVR_EXCLUDES "")
209-
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
210-
if(CMAKE_VERSION VERSION_GREATER 3.4)
211-
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
217+
if("--txt" IN_LIST GCOVR_ADDITIONAL_ARGS)
218+
set(Coverage_FORMAT txt)
219+
elseif("--csv" IN_LIST GCOVR_ADDITIONAL_ARGS)
220+
set(Coverage_FORMAT csv)
221+
elseif(("--cobertura" IN_LIST GCOVR_ADDITIONAL_ARGS)
222+
OR ("--cobertura-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS)
223+
OR ("--xml" IN_LIST GCOVR_ADDITIONAL_ARGS)
224+
OR ("--xml-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS)
225+
OR ("-x" IN_LIST GCOVR_ADDITIONAL_ARGS))
226+
set(Coverage_FORMAT cobertura)
227+
elseif("--sonarqube" IN_LIST GCOVR_ADDITIONAL_ARGS)
228+
set(Coverage_FORMAT sonarqube)
229+
elseif(("--json-summary" IN_LIST GCOVR_ADDITIONAL_ARGS)
230+
OR ("--json-summary-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS))
231+
set(Coverage_FORMAT json-summary)
232+
elseif(("--json" IN_LIST GCOVR_ADDITIONAL_ARGS)
233+
OR ("--json-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS))
234+
set(Coverage_FORMAT json-details)
235+
elseif(("--coveralls" IN_LIST GCOVR_ADDITIONAL_ARGS)
236+
OR ("--coveralls-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS))
237+
set(Coverage_FORMAT coveralls)
238+
elseif(("--html" IN_LIST GCOVR_ADDITIONAL_ARGS)
239+
OR ("--html-self-contained" IN_LIST GCOVR_ADDITIONAL_ARGS))
240+
set(Coverage_FORMAT html-single)
241+
elseif("--html-details" IN_LIST GCOVR_ADDITIONAL_ARGS)
242+
set(Coverage_FORMAT html-details)
243+
elseif("--html-nested" IN_LIST GCOVR_ADDITIONAL_ARGS)
244+
set(Coverage_FORMAT html-nested)
245+
else()
246+
if(NOT DEFINED Coverage_FORMAT)
247+
set(Coverage_FORMAT xml)
212248
endif()
213-
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
214-
endforeach()
215-
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
216-
217-
# Combine excludes to several -e arguments
218-
set(GCOVR_EXCLUDE_ARGS "")
219-
foreach(EXCLUDE ${GCOVR_EXCLUDES})
220-
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
221-
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
222-
endforeach()
223-
224-
# Set up commands which will be run to generate coverage data
225-
# Run tests
226-
set(GCOVR_XML_EXEC_TESTS_CMD
227-
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
228-
)
229-
# Running gcovr
230-
set(GCOVR_XML_CMD
231-
${GCOVR_PATH}
232-
--gcov-executable ${GCOV_TOOL}
233-
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
234-
--output ${Coverage_NAME}.xml
235-
--xml
236-
-r ${BASEDIR}
237-
${GCOVR_ADDITIONAL_ARGS}
238-
${GCOVR_EXCLUDE_ARGS}
239-
--object-directory=${PROJECT_BINARY_DIR}
240-
)
241249

242-
if(CODE_COVERAGE_VERBOSE)
243-
message(STATUS "Executed command report")
244-
245-
message(STATUS "Command to run tests: ")
246-
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
247-
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
248-
249-
message(STATUS "Command to generate gcovr XML coverage data: ")
250-
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
251-
message(STATUS "${GCOVR_XML_CMD_SPACED}")
250+
if ((Coverage_FORMAT STREQUAL "cobertura")
251+
OR (Coverage_FORMAT STREQUAL "xml"))
252+
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
253+
set(Coverage_FORMAT cobertura) # overwrite xml
254+
elseif(Coverage_FORMAT STREQUAL "sonarqube")
255+
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube)
256+
elseif(Coverage_FORMAT STREQUAL "json-summary")
257+
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
258+
elseif(Coverage_FORMAT STREQUAL "json-details")
259+
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
260+
elseif(Coverage_FORMAT STREQUAL "coveralls")
261+
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
262+
elseif(Coverage_FORMAT STREQUAL "csv")
263+
list(APPEND GCOVR_ADDITIONAL_ARGS --csv)
264+
elseif(Coverage_FORMAT STREQUAL "txt")
265+
list(APPEND GCOVR_ADDITIONAL_ARGS --txt)
266+
elseif(Coverage_FORMAT STREQUAL "html-single")
267+
list(APPEND GCOVR_ADDITIONAL_ARGS --html --html-self-contained)
268+
elseif(Coverage_FORMAT STREQUAL "html-nested")
269+
list(APPEND GCOVR_ADDITIONAL_ARGS --html --html-nested)
270+
elseif(Coverage_FORMAT STREQUAL "html-details")
271+
list(APPEND GCOVR_ADDITIONAL_ARGS --html --html-details)
272+
else()
273+
message(FATAL_ERROR "Unsupported output style ${Coverage_FORMAT}! Aborting...")
274+
endif()
252275
endif()
253276

254-
add_custom_target(${Coverage_NAME}
255-
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
256-
COMMAND ${GCOVR_XML_CMD}
257-
258-
BYPRODUCTS ${Coverage_NAME}.xml
259-
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
260-
DEPENDS ${Coverage_DEPENDENCIES}
261-
VERBATIM # Protect arguments to commands
262-
COMMENT "Running gcovr to produce Cobertura code coverage report."
263-
)
264-
265-
# Show info where to find the report
266-
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
267-
COMMAND ;
268-
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
269-
)
270-
endfunction() # setup_target_for_coverage_gcovr_xml
271-
272-
# Defines a target for running and collection code coverage information
273-
# Builds dependencies, runs the given executable and outputs reports.
274-
# NOTE! The executable should always have a ZERO as exit code otherwise
275-
# the coverage generation will not complete.
276-
#
277-
# setup_target_for_coverage_gcovr_html(
278-
# NAME ctest_coverage # New target name
279-
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
280-
# DEPENDENCIES executable_target # Dependencies to build first
281-
# BASE_DIRECTORY "../" # Base directory for report
282-
# # (defaults to PROJECT_SOURCE_DIR)
283-
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
284-
# # to BASE_DIRECTORY, with CMake 3.4+)
285-
# )
286-
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
287-
# GCVOR command.
288-
function(setup_target_for_coverage_gcovr_html)
289-
set(options NONE)
290-
set(oneValueArgs BASE_DIRECTORY NAME)
291-
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
292-
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
293-
294-
if(NOT GCOVR_PATH)
295-
message(FATAL_ERROR "gcovr not found! Aborting...")
296-
endif() # NOT GCOVR_PATH
297-
298-
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
299-
if(DEFINED Coverage_BASE_DIRECTORY)
300-
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
277+
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
278+
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
301279
else()
302-
set(BASEDIR ${PROJECT_SOURCE_DIR})
303-
endif()
304-
305-
# Optionally set --html-details
306-
if((NOT "--html-details" IN_LIST GCOVR_ADDITIONAL_ARGS)
307-
AND (NOT "--html-nested" IN_LIST GCOVR_ADDITIONAL_ARGS)
308-
AND (NOT "--html" IN_LIST GCOVR_ADDITIONAL_ARGS))
309-
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details)
280+
if((Coverage_FORMAT STREQUAL "html-details")
281+
OR (Coverage_FORMAT STREQUAL "html-nested"))
282+
set(GCOVR_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html)
283+
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
284+
elseif(Coverage_FORMAT STREQUAL "html-single")
285+
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
286+
elseif((Coverage_FORMAT STREQUAL "json-summary")
287+
OR (Coverage_FORMAT STREQUAL "json-details")
288+
OR (Coverage_FORMAT STREQUAL "coveralls"))
289+
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
290+
elseif(Coverage_FORMAT STREQUAL "txt")
291+
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
292+
elseif(Coverage_FORMAT STREQUAL "csv")
293+
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
294+
else()
295+
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
296+
endif()
297+
list(APPEND GCOVR_ADDITIONAL_ARGS --output ${GCOVR_OUTPUT_FILE})
310298
endif()
311299

312300
# Collect excludes (CMake 3.4+: Also compute absolute paths)
@@ -328,20 +316,23 @@ function(setup_target_for_coverage_gcovr_html)
328316

329317
# Set up commands which will be run to generate coverage data
330318
# Run tests
331-
set(GCOVR_HTML_EXEC_TESTS_CMD
319+
set(GCOVR_EXEC_TESTS_CMD
332320
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
333321
)
322+
334323
# Create folder
335-
set(GCOVR_HTML_FOLDER_CMD
336-
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
337-
)
324+
if(DEFINED GCOVR_CREATE_FOLDER)
325+
set(GCOVR_FOLDER_CMD
326+
${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
327+
else()
328+
set(GCOVR_FOLDER_CMD echo) # dummy
329+
endif()
330+
338331
# Running gcovr
339-
set(GCOVR_HTML_CMD
332+
set(GCOVR_CMD
340333
${GCOVR_PATH}
341334
--gcov-executable ${GCOV_TOOL}
342335
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
343-
--output ${Coverage_NAME}/index.html
344-
--html
345336
-r ${BASEDIR}
346337
${GCOVR_ADDITIONAL_ARGS}
347338
${GCOVR_EXCLUDE_ARGS}
@@ -352,37 +343,38 @@ function(setup_target_for_coverage_gcovr_html)
352343
message(STATUS "Executed command report")
353344

354345
message(STATUS "Command to run tests: ")
355-
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
356-
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
346+
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
347+
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
357348

358-
message(STATUS "Command to create a folder: ")
359-
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
360-
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
349+
if(NOT GCOVR_FOLDER_CMD STREQUAL "echo")
350+
message(STATUS "Command to create a folder: ")
351+
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
352+
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
353+
endif()
361354

362-
message(STATUS "Command to generate gcovr HTML coverage data: ")
363-
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
364-
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
355+
message(STATUS "Command to generate gcovr coverage data: ")
356+
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
357+
message(STATUS "${GCOVR_CMD_SPACED}")
365358
endif()
366359

367360
add_custom_target(${Coverage_NAME}
368-
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
369-
COMMAND ${GCOVR_HTML_FOLDER_CMD}
370-
COMMAND ${GCOVR_HTML_CMD}
361+
COMMAND ${GCOVR_EXEC_TESTS_CMD}
362+
COMMAND ${GCOVR_FOLDER_CMD}
363+
COMMAND ${GCOVR_CMD}
371364

372-
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
365+
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
373366
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
374367
DEPENDS ${Coverage_DEPENDENCIES}
375368
VERBATIM # Protect arguments to commands
376-
COMMENT "Running gcovr to produce HTML code coverage report."
369+
COMMENT "Running gcovr to produce code coverage report."
377370
)
378371

379372
# Show info where to find the report
380373
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
381374
COMMAND ;
382-
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
375+
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
383376
)
384-
385-
endfunction() # setup_target_for_coverage_gcovr_html
377+
endfunction() # setup_target_for_coverage_gcovr
386378

387379
function(append_coverage_compiler_flags)
388380
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)

Builds/CMake/RippledCov.cmake

+9-4
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,19 @@ if (coverage)
1313
set(TEST_PARALLELISM ${PROCESSOR_COUNT})
1414
endif()
1515

16-
if (NOT GCOVR_PATH)
17-
message(FATAL_ERROR "Cannot find gcovr, aborting ...")
16+
if (DEFINED CODE_COVERAGE_REPORT_FORMAT)
17+
set(CODE_COVERAGE_FORMAT ${CODE_COVERAGE_REPORT_FORMAT})
18+
elseif (DEFINED ENV{CODE_COVERAGE_REPORT_FORMAT})
19+
set(CODE_COVERAGE_FORMAT $ENV{CODE_COVERAGE_REPORT_FORMAT})
20+
else()
21+
set(CODE_COVERAGE_FORMAT html-details)
1822
endif()
1923

20-
set (GCOVR_ADDITIONAL_ARGS --exclude-noncode-lines --exclude-unreachable-branches -j ${PROCESSOR_COUNT} -s)
24+
set (GCOVR_ADDITIONAL_ARGS --exclude-throw-branches --exclude-noncode-lines --exclude-unreachable-branches -s)
2125

22-
setup_target_for_coverage_gcovr_html(
26+
setup_target_for_coverage_gcovr(
2327
NAME coverage_report
28+
FORMAT ${CODE_COVERAGE_FORMAT}
2429
EXECUTABLE rippled
2530
EXECUTABLE_ARGS -u --unittest-jobs ${TEST_PARALLELISM} --quiet --unittest-log
2631
EXCLUDE "src/test" "${CMAKE_BINARY_DIR}/proto_gen" "${CMAKE_BINARY_DIR}/proto_gen_grpc"

0 commit comments

Comments
 (0)