#!/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}/.lcovrc"
declare -r coverage_dir="${1:-${DEFAULT_BUILD_DIR}}/coverage"
declare -r FASTCOV_PATH="${HOME}/.local/bin/fastcov"
declare -A MODULE_INCLUDE=(
["ut"]="src/"
["it"]="src/"
["ubs-engine_ut_independent_ut"]="src/"
["ubs-engine_virtagent_ut_independent_ut"]="src/addons/virt_agent"
["ubs-engine_rmrs_plugin_ut_independent_ut"]="src/addons/rmrs"
["ubs-engine_ucache_plugin_ut_independent_ut"]="src/addons/ucache"
["ubs-engine_process_mem_ut_independent_ut"]="src/addons/process_mem"
)
COMMON_EXCLUDE=".h src/main/ test/ cmake-build-debug/"
ADDON_EXCLUDE="src/addons/rmrs src/addons/ucache src/addons/virt_agent"
declare -A MODULE_EXCLUDE=(
["ut"]="${COMMON_EXCLUDE}"
["it"]="${COMMON_EXCLUDE} test/UT/"
["ubs-engine_ut_independent_ut"]="${COMMON_EXCLUDE} ${ADDON_EXCLUDE}"
["ubs-engine_virtagent_ut_independent_ut"]="${COMMON_EXCLUDE}"
["ubs-engine_rmrs_plugin_ut_independent_ut"]="${COMMON_EXCLUDE}"
["ubs-engine_ucache_plugin_ut_independent_ut"]="${COMMON_EXCLUDE}"
["ubs-engine_process_mem_ut_independent_ut"]="${COMMON_EXCLUDE}"
)
function resolve_coverage_filters() {
local module="${COVERAGE_MODULE:-ut}"
include_patterns="${MODULE_INCLUDE[${module}]:-}"
exclude_patterns="${MODULE_EXCLUDE[${module}]:-}"
}
function generate_coverage_report() {
local output_dir="$1"
local lcovrc_file="$2"
local genhtml_path
genhtml_path="$(command -v genhtml)" || error_exit "genhtml not found in PATH"
mkdir -p "${output_dir}"
"${FASTCOV_PATH}" -b -n -p \
--include ${include_patterns} \
--exclude ${exclude_patterns} \
--lcov -o "${output_dir}/fastcov.info"
"${genhtml_path}" -q --config-file "${lcovrc_file}" \
-o "${output_dir}" "${output_dir}/fastcov.info"
}
function print_coverage_summary() {
local info_file="$1"
local lcovrc_file="$2"
local lcov_path
lcov_path="$(command -v lcov)" || error_exit "lcov not found in PATH"
echo ""
echo "=========================================="
echo " Coverage Summary Report"
echo "=========================================="
"${lcov_path}" --summary --config-file "${lcovrc_file}" "${info_file}" 2>&1 | grep -E "(lines|functions|branches)" || true
echo "=========================================="
}
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 \
; then
error_exit "Failed to install fastcov. Check network connection."
fi
fi
}
function main() {
local lcovrc_file="${DEFAULT_LCOVRC}"
local include_patterns=""
local exclude_patterns=""
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}"
resolve_coverage_filters
generate_coverage_report "${coverage_dir}" "${lcovrc_file}"
print_coverage_summary "${coverage_dir}/fastcov.info" "${lcovrc_file}"
echo ""
echo "Coverage module: ${COVERAGE_MODULE:-base}"
echo "Coverage report generated at: ${coverage_dir}/index.html"
}
main "$@"