#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
declare -r DEFAULT_BUILD_DIR="${PWD}/cmake-build-debug"
declare -r DEFAULT_LCOVRC="${PWD}/test/.lcovrc"
declare -r coverage_dir="${1:-${DEFAULT_BUILD_DIR}}/coverage"
declare -r FASTCOV_PATH="${HOME}/.local/bin/fastcov"
declare -A lcov_filters=([include]="" [exclude]="")
function parse_lcov_filters() {
local config_file="${1}"
while IFS= read -r line; do
line="$(sed -E 's/^\s*|\s*$//g; s/\s*=\s*/ /' <<< "${line}")"
[[ -z "${line}" ]] && continue
local filter_type="${line%% *}"
local pattern="${line#* }"
case "${filter_type}" in
include|exclude)
lcov_filters["${filter_type}"]+="${pattern} "
;;
esac
done < <(grep -E '^(include|exclude)' "${config_file}")
}
function generate_coverage_report() {
local output_dir="$1"
local lcovrc_file="$2"
local genhtml_path="$(command -v genhtml)" || error_exit "genhtml not found in PATH"
mkdir -p "${output_dir}"
"${FASTCOV_PATH}" -b -n -p \
--include ${lcov_filters[include]} \
--exclude ${lcov_filters[exclude]} \
--lcov -o "${output_dir}/fastcov.info"
"${genhtml_path}" -q --config-file "${lcovrc_file}" \
-o "${output_dir}" "${output_dir}/fastcov.info"
}
function error_exit() {
echo "[ERROR] $1" >&2
exit 1
}
ensure_fastcov_installed() {
if ! command -v fastcov >/dev/null 2>&1 && \
[[ ! -f "${FASTCOV_PATH}" ]]; then
echo "Installing fastcov via pip..."
if ! pip3 install fastcov \
--disable-pip-version-check --user \
--trusted-host repo.huaweicloud.com \
-i https://repo.huaweicloud.com/repository/pypi/simple/ \
; then
error_exit "Failed to install fastcov. Check network connection."
fi
fi
}
function main() {
local lcovrc_file="${2:-${DEFAULT_LCOVRC}}"
ensure_fastcov_installed || error_exit "Missing fastcov installed"
[[ -f "${lcovrc_file}" ]] || error_exit "Missing lcovrc file: ${lcovrc_file}"
[[ -f "${FASTCOV_PATH}" ]] || error_exit "Missing fastcov script: ${FASTCOV_PATH}"
parse_lcov_filters "${lcovrc_file}"
generate_coverage_report "${coverage_dir}" "${lcovrc_file}"
echo "Coverage report generated at: ${coverage_dir}/index.html"
}
main "$@"