Skip to content

Commit 382ed7b

Browse files
committed
coverage: fix lcov baseline
1 parent d0c98b7 commit 382ed7b

File tree

1 file changed

+102
-69
lines changed

1 file changed

+102
-69
lines changed

tools/coverage/lcov.sh

Lines changed: 102 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,25 @@ set -euo pipefail
44
set -o noglob
55

66
usage() {
7-
echo " -b TARGET_BASELINE The target used to collect the baseline"
8-
echo " -t TARGET_TESTS The test target"
9-
echo " -c CACHE The path to the bazel cache"
7+
echo "Usage:"
8+
echo " -b TARGET_BASELINE The target used to collect the baseline (-b \"target_1 target_2\")"
9+
echo " -t TARGET_TESTS The test target (-t \"target_1 target_2\")"
10+
echo " -c GCNO_DIR The path to the gcno files"
11+
echo " -d GCDA_DIR The path to the gcda files"
1012
echo " -s SKIP_HTML_REPORT Skip generation of HTML coverage report (default: false)."
1113
echo " -o OUTPUT_DIR Directory for output (default is temp directory)"
1214
echo " -h Display this help message"
1315
}
1416

17+
create_directory() {
18+
local dir="$1"
19+
if [ ! -d "$dir" ]; then
20+
echo "INFO: Creating directory: $dir"
21+
mkdir -p "$dir"
22+
fi
23+
}
24+
25+
# Parse options
1526
while getopts "b:t:c:d:o:sh" option; do
1627
case "${option}" in
1728
b) TARGET_BASELINE=${OPTARG} ;;
@@ -27,121 +38,143 @@ while getopts "b:t:c:d:o:sh" option; do
2738
esac
2839
done
2940

30-
if [[ -z "${TARGET_TESTS+x}" ]]; then
41+
# Validate required arguments
42+
if [[ -z "${TARGET_TESTS+x}" || -z "${GCNO_DIR+x}" || -z "${GCDA_DIR+x}" ]]; then
3143
echo "ERROR: Missing required arguments."
3244
usage
3345
exit 1
3446
fi
3547

36-
if [[ -z "${GCNO_DIR+x}" || -z "${GCDA_DIR+x}" ]]; then
37-
echo "ERROR: Missing required directories for .gcno or .gcda files."
38-
usage
39-
exit 1
40-
fi
41-
48+
# Set defaults
4249
SKIP_HTML_REPORT="${SKIP_HTML_REPORT:-false}"
43-
EXCLUDE_PATTERN="external/*|*gtest/*|/usr/*"
50+
EXCLUDE_PATTERN="external|gtest|/usr"
4451
TARGET_BASELINE="${TARGET_BASELINE:-"${TARGET_TESTS}"}"
4552
OUTPUT_DIR="${OUTPUT_DIR:-"$(mktemp -d)/cov_report"}"
46-
TARGET_DIR="${OUTPUT_DIR}/gcno_gcda"
47-
mkdir -p "${TARGET_DIR}"
53+
54+
create_directory "$OUTPUT_DIR"
4855

4956
echo "INFO: Baseline target: ${TARGET_BASELINE}"
50-
echo "INFO: Tests target: ${TARGET_TESTS}"
57+
echo "INFO: Test target: ${TARGET_TESTS}"
5158
echo "INFO: Output directory: ${OUTPUT_DIR}"
5259

5360
readonly WORKSPACE=$(cd "$(dirname "$(readlink -f "${0}")")" && bazel info workspace)
5461

55-
function run_baseline() {
56-
echo "\nINFO: Build baseline"
57-
echo "Baseline target: ${TARGET_BASELINE}"
62+
run_baseline() {
63+
echo -e "\nINFO: Building baseline target: ${TARGET_BASELINE}"
5864
bazel build \
5965
--collect_code_coverage \
6066
--experimental_fetch_all_coverage_outputs \
67+
--cxxopt="-O0" \
6168
-- ${TARGET_BASELINE}
6269
}
6370

64-
function run_coverage_tests() {
65-
echo "\nINFO: Run test"
66-
echo "Test target: ${TARGET_TESTS}"
71+
run_coverage_tests() {
72+
echo -e "\nINFO: Running test target: ${TARGET_TESTS}"
6773
bazel coverage \
6874
--nocache_test_results \
6975
--experimental_fetch_all_coverage_outputs \
7076
--cxxopt="-O0" \
77+
--instrumentation_filter="[/:]" \
7178
-- ${TARGET_TESTS}
7279
}
7380

74-
function generate_hashed_name() {
75-
local file_path="$1"
76-
local extension="${file_path##*.}" # Get the file extension (e.g., .gcno or .gcda)
77-
local path_no_extension="${file_path%".$extension"}" # Remove extension
78-
path_in_root=$(echo "$path_no_extension" | sed 's/.*\(bin\/.*\)/\1/') # Get file name from bin
79-
local hash=$(echo -n "$path_in_root" | sha256sum | awk '{print $1}') # Apply hash
80-
echo "$hash.$extension" # Return the hashed name with the original extension
81+
delete_coverage_files() {
82+
echo -e "\nINFO: Cleaning old .gcno and .gcda files"
83+
local directories=("${GCNO_DIR}" "${GCDA_DIR}")
84+
for dir in "${directories[@]}"; do
85+
find "$dir" -type f \( -name "*.gcno" -o -name "*.gcda" \) -exec chmod +w {} \; -exec rm -f {} \; || true
86+
done
8187
}
8288

83-
function delete_coverage_files() {
84-
echo "\nINFO: Clean old .gcno and .gcda files"
85-
echo "Input directory: $TARGET_DIR"
86-
find "$TARGET_DIR" -name "*.gcno" -exec rm -f {} \;
87-
find "$TARGET_DIR" -name "*.gcda" -exec rm -f {} \;
89+
generate_hashed_name() {
90+
local file_path="$1"
91+
local extension="${file_path##*.}"
92+
local path_no_extension="${file_path%.$extension}"
93+
local path_in_bin=$(echo "$path_no_extension" | awk -F"bin" "{print substr(\$0, length(\$1\"bin\") + 1)}")
94+
local hash=$(echo -n "$path_in_bin" | sha256sum | awk "{print \$1}")
95+
echo "$hash.$extension"
8896
}
8997

90-
function collect_coverage_data() {
91-
echo "\nINFO: Copy hashed .gcno and .gcda files"
92-
echo "Input gcno directory: $GCNO_DIR"
93-
echo "Input gcda directory: $GCDA_DIR"
94-
echo "Output dir: $TARGET_DIR"
98+
copy_coverage_files() {
99+
echo -e "\nINFO: Copy hashed .gcno and .gcda files"
100+
echo "Input directory: $1"
101+
echo "Output dir: $2"
95102
echo "Exclude pattern: $EXCLUDE_PATTERN"
96103

97-
find "$GCDA_DIR" -name "*.gcda" ! -path "$EXCLUDE_PATTERN" | while read -r file; do
98-
new_name=$(generate_hashed_name "$file" "$GCDA_DIR")
99-
cp "$file" "$TARGET_DIR/$new_name"
100-
echo "Copied gcda: $file -> $TARGET_DIR/$new_name"
101-
done
104+
mkdir -p "$2"
102105

103-
find "$GCNO_DIR" -name "*.gcno" ! -path "$EXCLUDE_PATTERN" | while read -r file; do
104-
new_name=$(generate_hashed_name "$file" "$GCNO_DIR")
105-
cp "$file" "$TARGET_DIR/$new_name"
106-
echo "Copied gcno: $file -> $TARGET_DIR/$new_name"
106+
find "$1" -type f \( -name "*.gcda" -o -name "*.gcno" \) ! -path "*/external/*" ! -path "*gtest*" ! -path "*test*" | while IFS= read -r file; do
107+
new_name=$(generate_hashed_name "$file" "$1")
108+
cp "$file" "$2/$new_name"
109+
echo "Copied: $file -> $2/$new_name"
107110
done
108111
}
109112

110-
function calculate_coverage() {
111-
echo "\nINFO: Generate coverage data"
112-
echo "Output directory: $OUTPUT_DIR"
113-
lcov --directory "$TARGET_DIR" \
113+
main() {
114+
pushd "${WORKSPACE}" || return
115+
116+
bazel clean
117+
delete_coverage_files
118+
run_baseline
119+
echo -e "\nINFO: Create baseline.info"
120+
lcov \
121+
--directory "${GCNO_DIR}" \
122+
--capture \
123+
-i \
124+
--output-file "${OUTPUT_DIR}/baseline.info"
125+
126+
echo -e "\nINFO: Filter baseline.info"
127+
lcov \
128+
--directory "${GCNO_DIR}" \
129+
--remove "${OUTPUT_DIR}/baseline.info" \
130+
'/usr/*' \
131+
'*external/*' \
132+
'*gtest*' \
133+
--ignore-errors unused \
134+
--ignore-errors empty \
135+
--output-file "${OUTPUT_DIR}/baseline_filtered.info"
136+
137+
run_coverage_tests
138+
139+
echo -e "\nINFO: Create tests.info"
140+
lcov \
141+
--directory "${GCDA_DIR}" \
114142
--capture \
115143
--ignore-errors source \
116-
--output-file "${OUTPUT_DIR}/coverage.info"
117-
lcov --remove "${OUTPUT_DIR}/coverage.info" \
144+
--output-file "${OUTPUT_DIR}/tests.info"
145+
146+
echo -e "\nINFO: Filter tests.info"
147+
lcov \
148+
--directory "${GCDA_DIR}" \
149+
--remove "${OUTPUT_DIR}/tests.info" \
118150
'/usr/*' \
119151
'external/*' \
120152
'*gtest*' \
121153
--ignore-errors unused \
122154
--ignore-errors source \
123-
--output-file "${OUTPUT_DIR}/coverage_filtered.info"
124-
sed -i 's|/proc/self/cwd/||g' "${OUTPUT_DIR}/coverage_filtered.info" # Remove file prefix
155+
--output-file "${OUTPUT_DIR}/tests_filtered.info"
156+
157+
sed -i 's|/__w/Team04/Team04||g' "${OUTPUT_DIR}/baseline_filtered.info"
158+
sed -i 's|/proc/self/cwd||g' "${OUTPUT_DIR}/baseline_filtered.info"
159+
sed -i 's|/__w/Team04/Team04||g' "${OUTPUT_DIR}/tests_filtered.info"
160+
sed -i 's|/proc/self/cwd/||g' "${OUTPUT_DIR}/tests_filtered.info"
161+
162+
echo -e "\nINFO: Merge baseline and tests coverage report"
163+
lcov \
164+
-a "${OUTPUT_DIR}/baseline_filtered.info" \
165+
-a "${OUTPUT_DIR}/tests_filtered.info" \
166+
-o "${OUTPUT_DIR}/coverage.info"
125167

126168
if [ "${SKIP_HTML_REPORT}" = false ]; then
127-
echo "\nINFO: Generate HTML coverage report"
128-
genhtml "${OUTPUT_DIR}/coverage_filtered.info" \
129-
--ignore-errors source \
130-
--output-directory "$OUTPUT_DIR"
169+
echo -e "\nINFO: Generating HTML coverage report"
170+
genhtml "${OUTPUT_DIR}/coverage.info" \
171+
--output-directory "${OUTPUT_DIR}"
131172
else
132-
echo "\nINFO: Generate coverage summary"
133-
lcov --summary "${OUTPUT_DIR}/coverage_filtered.info"
173+
echo -e "\nINFO: Generating coverage summary"
174+
lcov --summary "${OUTPUT_DIR}/coverage.info"
134175
fi
135-
}
136176

137-
function main() {
138-
pushd "${WORKSPACE}" || return
139-
run_baseline
140-
run_coverage_tests
141-
delete_coverage_files
142-
collect_coverage_data
143-
calculate_coverage
144-
popd || return
177+
popd &>/dev/null || true
145178
}
146179

147180
main

0 commit comments

Comments
 (0)