Skip to content

Commit

Permalink
chore: CPP CI unit test coverage report (#232)
Browse files Browse the repository at this point in the history
Co-authored-by: kschrief <[email protected]>
  • Loading branch information
AdityaKasar and kschrief authored Dec 5, 2024
1 parent ab8d727 commit 5780b58
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 3 deletions.
6 changes: 3 additions & 3 deletions languages/cpp/src/shared/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ set(FIREBOLT_LOGLEVEL "Info" CACHE STRING "Log level to be enabled")
option(FIREBOLT_ENABLE_STATIC_LIB "Create Firebolt library as Static library" OFF)
option(ENABLE_TESTS "Build openrpc native test" ON)
option(ENABLE_UNIT_TESTS "Enable unit test" ON)
option(ENABLE_COVERAGE "Enable code coverage build." OFF)
option(ENABLE_COVERAGE "Enable code coverage build." ON)

if (FIREBOLT_ENABLE_STATIC_LIB)
set(FIREBOLT_LIBRARY_TYPE STATIC)
Expand Down Expand Up @@ -100,14 +100,14 @@ message("CMAKE_PREFIX_PATH: " ${CMAKE_PREFIX_PATH})

find_package(WPEFramework CONFIG REQUIRED)

if (ENABLE_TESTS AND ENABLE_COVERAGE)
if (ENABLE_UNIT_TESTS AND ENABLE_COVERAGE)
include(CodeCoverage)
append_coverage_compiler_flags()
endif()

add_subdirectory(src)

if (ENABLE_TESTS)
if (ENABLE_TESTS OR ENABLE_UNIT_TESTS)
enable_testing()
add_subdirectory(test)
endif()
Expand Down
163 changes: 163 additions & 0 deletions languages/cpp/src/shared/cmake/CodeCoverage.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@

include(CMakeParseArguments)

if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(IS_CLANG TRUE)
else()
set(IS_CLANG FALSE)
endif()
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IS_GCC TRUE)
else()
set(IS_GCC FALSE)
endif()

if(NOT ${IS_CLANG} AND NOT ${IS_GCC})
message(FATAL_ERROR "Compiler is not gcc/clang! Aborting...")
endif()

find_program(GCOVR_PATH gcovr)

set(COVERAGE_COMPILER_FLAGS "-g3 -O0 --coverage")
set(CMAKE_CXX_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS} FORCE)
set(CMAKE_C_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS} FORCE)
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "-lgcov" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "" FORCE)
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE)

if(NOT
CMAKE_BUILD_TYPE
STREQUAL
"Debug")
message(WARNING "Cov results with non-Debug build may be misleading")
endif()

if(${IS_GCC})
link_libraries(gcov)
endif()

function(setup_target_for_coverage_gcovr_html)
message("Inside setup_target_for_coverage_gcovr_html()")
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH

set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs
EXCLUDE
EXECUTABLE
EXECUTABLE_ARGS
DEPENDENCIES)
cmake_parse_arguments(
Coverage
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN})

# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()

# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES}
${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(
EXCLUDE
${EXCLUDE}
ABSOLUTE
BASE_DIR
${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)

# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()

# Set up commands which will be run to generate coverage data Run tests
set(GCOVR_HTML_EXEC_TESTS_CMD ${Coverage_EXECUTABLE}
${Coverage_EXECUTABLE_ARGS})
# Create folder
set(GCOVR_HTML_FOLDER_CMD
${CMAKE_COMMAND}
-E
make_directory
${PROJECT_BINARY_DIR}/${Coverage_NAME})

# Running gcovr
set(GCOVR_EXTRA_FLAGS
--json-summary
--json-summary-pretty
--html-theme
github.green
--html-title "FireboltSDK Coverage Report"
)
set(GCOVR_HTML_CMD
${GCOVR_PATH}
${GCOVR_EXTRA_FLAGS}
--html
${Coverage_NAME}/index.html
--html-details
--json-summary
${Coverage_NAME}/summary.json
--json-summary-pretty
--cobertura
${Coverage_NAME}/coverage.cobertura.xml
--cobertura-pretty
--decisions
-r
${BASEDIR}
${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR})

add_custom_target(
${Coverage_NAME}
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD} || true
COMMAND ${GCOVR_HTML_FOLDER_CMD}
COMMAND ${GCOVR_HTML_CMD}
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report
# directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce HTML code coverage report.")

# Show info where to find the report
add_custom_command(
TARGET ${Coverage_NAME}
POST_BUILD
COMMAND ;
COMMENT
"Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_gcovr_html

function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
PARENT_SCOPE)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
PARENT_SCOPE)
message(
STATUS
"Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}"
)
endfunction()

0 comments on commit 5780b58

Please sign in to comment.