diff --git a/.github/workflows/lcov.yml b/.github/workflows/lcov.yml new file mode 100644 index 00000000..f33d9ef1 --- /dev/null +++ b/.github/workflows/lcov.yml @@ -0,0 +1,42 @@ +name: Coverage + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + coverage: + name: Test Coverage + runs-on: ubuntu-latest + container: + image: vsaglib/vsag:ubuntu + steps: + - uses: actions/checkout@v4 + - name: Load Cache + uses: actions/cache@v4.1.2 + with: + path: ./build/ + key: build-${{ hashFiles('./CMakeLists.txt') }}-${{ hashFiles('./.circleci/fresh_ci_cache.commit') }} + - name: Compile + run: make cov + - name: Run Test + run: | + ./scripts/test_parallel_bg.sh + ./build/mockimpl/tests_mockimpl -d yes ${UT_FILTER} --allow-running-no-tests ${UT_SHARD} + - name: Collect Coverage Info + run: bash scripts/collect_cpp_coverage.sh + - name: Generate HTML + run: genhtml --output-directory coverage/html coverage/coverage.info + - name: Upload HTML coverage report + uses: actions/upload-artifact@v4 + with: + name: coverage-report-${{ github.run_id }} + path: coverage/html/ + compression-level: 1 + retention-days: 3 + overwrite: 'true' + - name: Set Threshold + run: bash ./scripts/check_cov.sh + diff --git a/Makefile b/Makefile index 0143968b..ee6f8361 100644 --- a/Makefile +++ b/Makefile @@ -100,8 +100,8 @@ test_cov: cov ## Build and run unit tests with code coverage enabled. ./build/tests/unittests -d yes ${UT_FILTER} --allow-running-no-tests ${UT_SHARD} ./build/tests/functests -d yes ${UT_FILTER} --allow-running-no-tests ${UT_SHARD} ./build/mockimpl/tests_mockimpl -d yes ${UT_FILTER} --allow-running-no-tests ${UT_SHARD} - bash scripts/aci/collect_cpp_coverage.sh - genhtml --output-directory testresult/coverage/html testresult/coverage/coverage.info --ignore-errors inconsistent,inconsistent + bash scripts/collect_cpp_coverage.sh + genhtml --output-directory coverage/coverage/html coverage/coverage.info --ignore-errors inconsistent,inconsistent .PHONY: clean clean: ## Clear build/ directory. diff --git a/scripts/check_cov.sh b/scripts/check_cov.sh new file mode 100644 index 00000000..2888fcc4 --- /dev/null +++ b/scripts/check_cov.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +line_coverage=`lcov --summary coverage/coverage.info | grep "lines......" | awk '/lines/ { print $2 }' | cut -d '%' -f 1` +line_coverage=$(printf "%.0f" $line_coverage) +if [ "$line_coverage" -gt 84 ]; then + echo "line coverage is ${line_coverage}, more than 84" + exit 0; +else + echo "line coverage is ${line_coverage}, less than 84" + exit 1; +fi diff --git a/scripts/collect_cpp_coverage.sh b/scripts/collect_cpp_coverage.sh new file mode 100644 index 00000000..c788a3bf --- /dev/null +++ b/scripts/collect_cpp_coverage.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -e +set -x + +SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +ROOT_DIR="${SCRIPTS_DIR}/../" + +COVERAGE_DIR="${ROOT_DIR}/coverage" +if [ -d "${COVERAGE_DIR}" ]; then + rm -rf "${COVERAGE_DIR:?}"/* +else + mkdir -p "${COVERAGE_DIR}" +fi + +lcov --gcov-tool ${SCRIPTS_DIR}/gcov_for_clang.sh \ + --rc branch_coverage=1 \ + --rc geninfo_unexecuted_blocks=1 \ + --include "*/vsag/include/*" \ + --include "*/vsag/src/*" \ + --exclude "*/vsag/include/vsag/expected.hpp*" \ + --exclude "*_test.cpp" \ + --capture \ + --directory . \ + --output-file "${COVERAGE_DIR}/coverage_ut.info" + +pushd "${COVERAGE_DIR}" +coverages=$(ls coverage_*.info) +if [ ! "$coverages" ];then + echo "no coverage file" + exit 0 +fi +lcov_command="lcov" +for coverage in $coverages; do + echo "$coverage" + lcov_command="$lcov_command -a $coverage" +done +$lcov_command -o coverage.info \ + --rc branch_coverage=1 \ + --ignore-errors inconsistent,inconsistent \ + --ignore-errors corrupt,corrupt +popd diff --git a/scripts/gcov_for_clang.sh b/scripts/gcov_for_clang.sh new file mode 100755 index 00000000..ec6863ca --- /dev/null +++ b/scripts/gcov_for_clang.sh @@ -0,0 +1,3 @@ +#!/bin/bash +exec gcov "$@" +