From 3a53ca414a90ef0624d183893955146ac199105b Mon Sep 17 00:00:00 2001 From: Matt Alvarado Date: Tue, 28 Apr 2026 21:55:35 -0400 Subject: [PATCH 1/4] Add in a coverage target to generate code coverage reports --- CMakeLists.txt | 12 ++++++++++++ README.md | 15 +++++++++++++++ cmake/coverage.cmake | 31 +++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 cmake/coverage.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 6afea221..d7225aa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,11 +50,23 @@ option(BUILD_OPENCV "Use OpenCV if found on the host system" OFF) option(BUILD_PYTHON_BINDINGS "Build Python bindings with pybind11." OFF) option(BUILD_JSON_SERIALIZATION "Build json type serialization with nlohmann json." OFF) option(ENABLE_ASAN "Build with AddressSanitizer instrumentation." OFF) +option(ENABLE_COVERAGE "Build with code coverage instrumentation." OFF) if (BUILD_TESTS) enable_testing() endif() +if (ENABLE_COVERAGE) + if (MSVC) + message(FATAL_ERROR "ENABLE_COVERAGE is only supported with Clang or GCC toolchains.") + endif() + + add_compile_options(--coverage -O0 -g) + add_link_options(--coverage) + + include(cmake/coverage.cmake) +endif() + # # We want to build "Release" by default # diff --git a/README.md b/README.md index 859930cc..8af9fa39 100644 --- a/README.md +++ b/README.md @@ -197,6 +197,21 @@ the following CMake argument should be set This will require a system installation of googletest, or an installation which can be pointed to with CMake's `CMAKE_PREFIX_PATH` argument +### Code Coverage + +LibMultiSense supports generating unit test coverage reports using `lcov` and `genhtml`. +To enable coverage instrumentation, set the following CMake argument: + + -DENABLE_COVERAGE=ON + +Once enabled, you can generate the coverage report by running: + +```bash +make coverage +``` + +The report will be generated in `build/coverage_report/index.html`. This requires `lcov` and `genhtml` to be installed on the system and is supported on Linux with GCC or Clang. + --- ## Installation diff --git a/cmake/coverage.cmake b/cmake/coverage.cmake new file mode 100644 index 00000000..b2d61599 --- /dev/null +++ b/cmake/coverage.cmake @@ -0,0 +1,31 @@ +# +# Coverage reporting +# + +find_program(LCOV_PATH lcov) +find_program(GENHTML_PATH genhtml) + +if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Coverage target will not be available.") +endif() + +if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Coverage target will not be available.") +endif() + +add_custom_target(coverage + # Cleanup old data + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters + # Run tests + COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure + # Capture coverage data + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture --output-file ${CMAKE_BINARY_DIR}/coverage.info --ignore-errors mismatch + # Remove system headers and third-party code + COMMAND ${LCOV_PATH} --remove ${CMAKE_BINARY_DIR}/coverage.info '/usr/*' '*/test/*' '*/vcpkg_installed/*' '*/details/legacy/*' --output-file ${CMAKE_BINARY_DIR}/coverage_filtered.info --ignore-errors unused + # Generate HTML report + COMMAND ${GENHTML_PATH} ${CMAKE_BINARY_DIR}/coverage_filtered.info --output-directory ${CMAKE_BINARY_DIR}/coverage_report + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating unit test coverage report" +) + +message(STATUS "Coverage target 'coverage' added. Run 'make coverage' to generate report.") From 82a415b5bae3e8e726fc8211a96f4983e2006d4c Mon Sep 17 00:00:00 2001 From: Matt Alvarado Date: Tue, 28 Apr 2026 21:59:08 -0400 Subject: [PATCH 2/4] Add codecov badge to README --- .github/workflows/build.yml | 13 +++++++++++-- README.md | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 283e2981..bc909e37 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: - name: Install Ubuntu dependencies run: | sudo apt-get update - sudo apt-get install -y libgtest-dev nlohmann-json3-dev pybind11-dev python3-pip ninja-build + sudo apt-get install -y libgtest-dev nlohmann-json3-dev pybind11-dev python3-pip ninja-build lcov - name: Install Clang if: matrix.compiler == 'clang' @@ -75,12 +75,21 @@ jobs: -DBUILD_TESTS=ON \ -DBUILD_JSON_SERIALIZATION=ON \ -DBUILD_LEGACY_API=OFF \ + -DENABLE_COVERAGE=ON \ -DCMAKE_INSTALL_PREFIX=install-debug cmake --build build -j "$(nproc)" - make -C build test + cmake --build build --target coverage cmake --install build + - name: Upload Coverage to Codecov + if: matrix.compiler == 'gcc' && matrix.ubuntu == 'ubuntu-24.04' + uses: codecov/codecov-action@v4 + with: + file: build/coverage_filtered.info + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + build-macos: name: Build on macOS (${{ matrix.compiler }}) runs-on: macOS-latest diff --git a/README.md b/README.md index 8af9fa39..b2b23946 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # LibMultiSense +[![codecov](https://codecov.io/gh/carnegierobotics/LibMultiSense/branch/master/graph/badge.svg)](https://codecov.io/gh/carnegierobotics/LibMultiSense) + LibMultiSense is a C++ and Python library designed to simplify interaction with the MultiSense S family of stereo sensors developed by Carnegie Robotics. It provides a comprehensive, easy-to-use API for capturing and processing stereo sensor data an generating depth images, color images, and 3D point clouds. From 787b726570783149398e8ef49bbe34e5a846ffe4 Mon Sep 17 00:00:00 2001 From: Matt Alvarado Date: Tue, 28 Apr 2026 22:06:19 -0400 Subject: [PATCH 3/4] Fix issues with code coverage on 22.04 --- cmake/coverage.cmake | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cmake/coverage.cmake b/cmake/coverage.cmake index b2d61599..0bfc72e8 100644 --- a/cmake/coverage.cmake +++ b/cmake/coverage.cmake @@ -13,15 +13,27 @@ if(NOT GENHTML_PATH) message(FATAL_ERROR "genhtml not found! Coverage target will not be available.") endif() +# Detect lcov version to use compatible flags +execute_process(COMMAND ${LCOV_PATH} --version OUTPUT_VARIABLE LCOV_VERSION_OUTPUT) +if(LCOV_VERSION_OUTPUT MATCHES "version ([2-9][0-9]*\\.[0-9]+)") + message(STATUS "Detected lcov version 2.0+ (${CMAKE_MATCH_1})") + # For lcov 2.0+, we need to ignore certain errors that were previously warnings + set(LCOV_FLAGS --ignore-errors mismatch,unused) +else() + message(STATUS "Detected lcov version 1.x") + # For lcov 1.x, we use older ignore-errors categories + set(LCOV_FLAGS --ignore-errors gcov,source) +endif() + add_custom_target(coverage # Cleanup old data COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters # Run tests COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure # Capture coverage data - COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture --output-file ${CMAKE_BINARY_DIR}/coverage.info --ignore-errors mismatch + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture --output-file ${CMAKE_BINARY_DIR}/coverage.info ${LCOV_FLAGS} # Remove system headers and third-party code - COMMAND ${LCOV_PATH} --remove ${CMAKE_BINARY_DIR}/coverage.info '/usr/*' '*/test/*' '*/vcpkg_installed/*' '*/details/legacy/*' --output-file ${CMAKE_BINARY_DIR}/coverage_filtered.info --ignore-errors unused + COMMAND ${LCOV_PATH} --remove ${CMAKE_BINARY_DIR}/coverage.info '/usr/*' '*/test/*' '*/vcpkg_installed/*' '*/details/legacy/*' --output-file ${CMAKE_BINARY_DIR}/coverage_filtered.info ${LCOV_FLAGS} # Generate HTML report COMMAND ${GENHTML_PATH} ${CMAKE_BINARY_DIR}/coverage_filtered.info --output-directory ${CMAKE_BINARY_DIR}/coverage_report WORKING_DIRECTORY ${CMAKE_BINARY_DIR} From 086e9835a78cd6307f470104e4d79b47949ed3be Mon Sep 17 00:00:00 2001 From: Matt Alvarado Date: Tue, 28 Apr 2026 22:12:03 -0400 Subject: [PATCH 4/4] Bugfix --- .github/workflows/build.yml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc909e37..7fbf7627 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: - name: Build Release run: | - cmake -B build -S . \ + cmake -B build-release -S . \ -DCMAKE_C_COMPILER="${CC}" \ -DCMAKE_CXX_COMPILER="${CXX}" \ -DCMAKE_BUILD_TYPE=Release \ @@ -46,9 +46,9 @@ jobs: -DBUILD_LEGACY_API=OFF \ -DCMAKE_INSTALL_PREFIX=install-release - cmake --build build -j "$(nproc)" - make -C build test - cmake --install build + cmake --build build-release -j "$(nproc)" + make -C build-release test + cmake --install build-release mkdir pip-wheel python -m venv .venv source .venv/bin/activate @@ -68,25 +68,27 @@ jobs: - name: Build Debug run: | - cmake -B build -S . \ + cmake -B build-debug -S . \ -DCMAKE_C_COMPILER="${CC}" \ -DCMAKE_CXX_COMPILER="${CXX}" \ -DCMAKE_BUILD_TYPE=Debug \ -DBUILD_TESTS=ON \ -DBUILD_JSON_SERIALIZATION=ON \ -DBUILD_LEGACY_API=OFF \ - -DENABLE_COVERAGE=ON \ + -DENABLE_COVERAGE=${{ matrix.compiler == 'gcc' && 'ON' || 'OFF' }} \ -DCMAKE_INSTALL_PREFIX=install-debug - cmake --build build -j "$(nproc)" - cmake --build build --target coverage - cmake --install build + cmake --build build-debug -j "$(nproc)" + if [ "${{ matrix.compiler }}" = "gcc" ]; then + cmake --build build-debug --target coverage + fi + cmake --install build-debug - name: Upload Coverage to Codecov - if: matrix.compiler == 'gcc' && matrix.ubuntu == 'ubuntu-24.04' + if: matrix.compiler == 'gcc' uses: codecov/codecov-action@v4 with: - file: build/coverage_filtered.info + file: build-debug/coverage_filtered.info fail_ci_if_error: false token: ${{ secrets.CODECOV_TOKEN }}