Skip to content

Commit

Permalink
Add coverage option
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-PLACET committed Dec 17, 2024
1 parent e03366f commit 69dcba7
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 7 deletions.
25 changes: 23 additions & 2 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ jobs:
if: matrix.target-arch.name == 'Win32' # Note: this is not a mandatory limitation in any context, we add this just to have at least one configuration testing that feature
run: echo "SPARROW_CHECKS='$SPARROW_CHECKS -DSPARROW_ENABLE_32BIT_SIZE_LIMIT=ON'" >> $GITHUB_ENV

- name: Enable tests coverage
if: matrix.config.name == 'Debug'
run: |
choco install opencppcoverage
echo "TEST_COVERAGE_ACTIVATION=' -DENABLE_COVERAGE=ON'" >> $GITHUB_ENV
- name: Set CMake generator environment variable
run: |
echo "CMAKE_GENERATOR=${{ matrix.build-system.name }}" >> $GITHUB_ENV
Expand Down Expand Up @@ -182,7 +188,8 @@ jobs:
$SPARROW_ADDITIONAL_OPTIONS \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL \
$TEST_COVERAGE_ACTIVATION
- name: Build library
working-directory: build
Expand All @@ -207,7 +214,21 @@ jobs:
name: test_sparrow_lib_report_Windows_${{ matrix.toolchain.compiler }}_${{ matrix.build-system.name }}_${{ matrix.config.name }}_${{ matrix.target-arch.name }}_date-polyfill_${{ matrix.toolchain.date-polyfill}}
path: '**/test_sparrow_lib_report.xml'

- name: Tests coverage
if: matrix.config.name == 'Debug'
working-directory: build
run: |
cmake --build . --config Debug --target generate_cobertura
- name: Produce the coverage report
if: matrix.config.name == 'Debug'
uses: dennisjensen95/[email protected]
with:
coverage-filepath: 'build/coverage_reports/cobertura.xml'
branch: main
threshold-total: 50
threshold-change: 50

- name: Run all examples
working-directory: build
run: cmake --build . --config ${{matrix.config.name}} --target run_examples

20 changes: 16 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.22)
cmake_minimum_required(VERSION 3.10)

# This is better specified per target, but cmake keeps ignoring these language version
# specification when building this project by itself, in particular the gnu extensions,
Expand Down Expand Up @@ -47,6 +47,9 @@ if(CMAKE_CXX_COMPILER_LAUNCHER)
message(STATUS "Using C++ compiler launcher: ${CMAKE_CXX_COMPILER_LAUNCHER}")
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
message(DEBUG "CMake module path: ${CMAKE_MODULE_PATH}")

# Versionning
# ===========

Expand Down Expand Up @@ -90,6 +93,12 @@ OPTION(USE_LARGE_INT_PLACEHOLDERS "use types without api for big integers" OFF)

OPTION(SPARROW_TARGET_32BIT "Test 32bit support" OFF)

OPTION(ENABLE_COVERAGE "Enable test coverage" OFF)

if(ENABLE_COVERAGE)
include(code_coverage)
endif()

include(CheckCXXSymbolExists)

if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
Expand All @@ -113,13 +122,13 @@ OPTION(ACTIVATE_LINTER "Create targets to run clang-format" OFF)
cmake_dependent_option(ACTIVATE_LINTER_DURING_COMPILATION "Run linter during the compilation" ON "ACTIVATE_LINTER" OFF)

if(ACTIVATE_LINTER)
include(cmake/clang-format.cmake)
include(cmake/clang-tidy.cmake)
include(clang-format)
include(clang-tidy)
endif()

# Sanitizers
# ==========
include(cmake/sanitizers.cmake)
include(sanitizers)

# Dependencies
# ============
Expand Down Expand Up @@ -272,6 +281,9 @@ target_include_directories(sparrow PUBLIC
set_target_properties(sparrow PROPERTIES CMAKE_CXX_EXTENSIONS OFF)
target_compile_features(sparrow PUBLIC cxx_std_20)
target_link_libraries(sparrow PUBLIC ${SPARROW_INTERFACE_DEPENDENCIES})
if(ENABLE_COVERAGE)
enable_coverage(sparrow)
endif()

if (BUILD_TESTS)
enable_testing()
Expand Down
98 changes: 98 additions & 0 deletions cmake/code_coverage.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif()

set(COVERAGE_REPORT_PATH "${CMAKE_BINARY_DIR}/coverage_reports" CACHE PATH "Path to store coverage reports")
set(COBERTURA_REPORT_PATH "${COVERAGE_REPORT_PATH}/cobertura.xml" CACHE PATH "Path to store cobertura report")
set(COVERAGE_TARGETS_FOLDER "Tests utilities/Code Coverage")

if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
find_program(OpenCPPCoverage OpenCppCoverage.exe opencppcoverage.exe REQUIRED
PATHS "C:/Program Files/OpenCppCoverage" "C:/Program Files (x86)/OpenCppCoverage")

cmake_path(CONVERT ${CMAKE_SOURCE_DIR} TO_NATIVE_PATH_LIST OPENCPPCOVERAGE_SOURCES)
set(OPENCPPCOVERAGE_COMMON_ARGS --sources=${OPENCPPCOVERAGE_SOURCES} --modules=${OPENCPPCOVERAGE_SOURCES} --excluded_sources=test*)

add_custom_target(generate_cobertura
COMMAND ${OpenCPPCoverage}
${OPENCPPCOVERAGE_COMMON_ARGS}
--export_type=cobertura:${COBERTURA_REPORT_PATH}
-- $<TARGET_FILE:test_sparrow_lib>
DEPENDS test_sparrow_lib
COMMENT "Generating coverage cobertura report with OpenCppCoverage: ${COBERTURA_REPORT_PATH}"
)
set(TARGET_PROPERTIES generate_cobertura PROPERTIES FOLDER ${COVERAGE_TARGETS_FOLDER})

add_custom_target(generate_html_coverage_report
COMMAND ${OpenCPPCoverage}
${OPENCPPCOVERAGE_COMMON_ARGS}
--export_type=html:${COVERAGE_REPORT_PATH}
-- $<TARGET_FILE:test_sparrow_lib>
DEPENDS test_sparrow_lib
COMMENT "Generating coverage report with OpenCppCoverage: ${COVERAGE_REPORT_PATH}"
)
set(TARGET_PROPERTIES generate_cobertura PROPERTIES FOLDER "Tests utilities/Code Coverage")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
find_program(llvm-cov llvm-cov REQUIRED)
find_program(gcovr gcovr REQUIRED)
find_program(doxide doxide REQUIRED PATHS ${doxide_ROOT})

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(gcov_executable llvm-cov gcov)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(gcov_executable gcov)
endif()

if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_custom_target(merge_gcov
COMMAND ${CMAKE_COMMAND} -E rm -f "${CMAKE_BINARY_DIR}/coverage.gcov"
COMMAND for /r %f in (*.gcda) do ${gcov_executable} --stdout "%f" >> ${CMAKE_BINARY_DIR}/coverage.gcov
DEPENDS run_tests)
else()
add_custom_target(merge_gcov
COMMAND ${CMAKE_COMMAND} -E rm -f "${CMAKE_BINARY_DIR}/coverage.gcov"
COMMAND find . -name '*.gcda' | xargs ${gcov_executable} --stdout > ${CMAKE_BINARY_DIR}/coverage.gcov
DEPENDS run_tests)
endif()
set_target_properties(merge_gcov PROPERTIES FOLDER ${COVERAGE_TARGETS_FOLDER})

add_custom_target(doxide_generate_json
COMMAND ${doxide} cover --coverage ${CMAKE_BINARY_DIR}/coverage.gcov > ${CMAKE_BINARY_DIR}/doxide_coverage.json
DEPENDS merge_gcov
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Generating coverage report with doxide: ${CMAKE_BINARY_DIR}/doxide_coverage.json"
)
set_target_properties(doxide_generate_json PROPERTIES FOLDER ${COVERAGE_TARGETS_FOLDER})

add_custom_target(generate_html_coverage_report
COMMAND ${gcovr} --html-details ${COVERAGE_REPORT_PATH}/coverage.html
--exclude-function-lines
--exclude-noncode-lines
--json-add-tracefile doxide_coverage.json
-r ${CMAKE_SOURCE_DIR}
DEPENDS doxide_generate_json
COMMENT "Generating coverage report with gcovr: ${COVERAGE_REPORT_PATH}/coverage.html")
set_target_properties(generate_html_coverage_report PROPERTIES FOLDER ${COVERAGE_TARGETS_FOLDER})

add_custom_target(generate_cobertura
COMMAND ${gcovr} --xml -o ${COBERTURA_REPORT_PATH}
--exclude-function-lines
--exclude-noncode-lines
--json-add-tracefile doxide_coverage.json
-r ${CMAKE_SOURCE_DIR}
DEPENDS doxide_generate_json
COMMENT "Generating coverage report with gcovr: ${CMAKE_BINARY_DIR}/cobertura.xml")
set_target_properties(generate_cobertura PROPERTIES FOLDER ${COVERAGE_TARGETS_FOLDER})
endif()

function(enable_coverage target)
set(CLANG_COVERAGE_FLAGS --coverage -fprofile-instr-generate -fcoverage-mapping -fno-inline -fno-elide-constructors)
set(GCC_COVERAGE_FLAGS --coverage -fno-inline -fno-inline-small-functions -fno-default-inline)

target_compile_options(${target} PRIVATE
$<$<CXX_COMPILER_ID:Clang>:${CLANG_COVERAGE_FLAGS}>
$<$<CXX_COMPILER_ID:GNU>:${GCC_COVERAGE_FLAGS}>)
target_link_options(${target} PRIVATE
$<$<CXX_COMPILER_ID:Clang>:${CLANG_COVERAGE_FLAGS}>
$<$<CXX_COMPILER_ID:GNU>:${GCC_COVERAGE_FLAGS}>)
endfunction(enable_coverage target)
9 changes: 9 additions & 0 deletions doxide.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
title: Sparrow
description:
files:
- "include/*.hpp"
- "include/**/*.hpp"
- "include/*.h"
- "include/**/*.h"
- "src/*.cpp"
- "src/**/*.cpp"
7 changes: 6 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.8)
cmake_minimum_required(VERSION 3.10)

enable_testing()

Expand Down Expand Up @@ -199,6 +199,11 @@ target_compile_options(${test_target}
target_link_options(${test_target}
PRIVATE
$<$<BOOL:USE_SANITIZER>:${SANITIZER_LINK_OPTIONS}>)

if(ENABLE_COVERAGE)
enable_coverage(${test_target})
endif()

# We do not use non-standard C++
set_target_properties(${test_target} PROPERTIES CMAKE_CXX_EXTENSIONS OFF)
target_compile_features(${test_target} PRIVATE cxx_std_20)
Expand Down

0 comments on commit 69dcba7

Please sign in to comment.