@@ -4,18 +4,29 @@ set -euo pipefail
4
4
set -o noglob
5
5
6
6
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"
10
12
echo " -s SKIP_HTML_REPORT Skip generation of HTML coverage report (default: false)."
11
13
echo " -o OUTPUT_DIR Directory for output (default is temp directory)"
12
14
echo " -h Display this help message"
13
15
}
14
16
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
15
26
while getopts " b:t:c:d:o:sh" option; do
16
27
case " ${option} " in
17
- b) TARGET_BASELINE= ${OPTARG} ;;
18
- t) TARGET_TESTS= ${OPTARG} ;;
28
+ b) TARGET_BASELINE+=( ${OPTARG} ) ;;
29
+ t) TARGET_TESTS+=( ${OPTARG} ) ;;
19
30
c) GCNO_DIR=${OPTARG} ;;
20
31
d) GCDA_DIR=${OPTARG} ;;
21
32
s) SKIP_HTML_REPORT=true ;;
@@ -27,120 +38,145 @@ while getopts "b:t:c:d:o:sh" option; do
27
38
esac
28
39
done
29
40
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
31
43
echo " ERROR: Missing required arguments."
32
44
usage
33
45
exit 1
34
46
fi
35
47
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
42
49
SKIP_HTML_REPORT=" ${SKIP_HTML_REPORT:- false} "
43
- EXCLUDE_PATTERN=" external/*|* gtest/* |/usr/* "
50
+ EXCLUDE_PATTERN=" external| gtest|/usr"
44
51
TARGET_BASELINE=" ${TARGET_BASELINE:- " ${TARGET_TESTS} " } "
45
52
OUTPUT_DIR=" ${OUTPUT_DIR:- " $( mktemp -d) /cov_report" } "
46
- TARGET_DIR=" ${OUTPUT_DIR} /gcno_gcda"
47
- mkdir -p " ${TARGET_DIR} "
53
+ FILTERED_GCNO_DIR=" ${OUTPUT_DIR} /gcno"
54
+ FILTERED_GCDA_DIR=" ${OUTPUT_DIR} /gcda"
55
+
56
+ create_directory " $OUTPUT_DIR "
57
+ create_directory " $FILTERED_GCNO_DIR "
58
+ create_directory " $FILTERED_GCDA_DIR "
48
59
49
60
echo " INFO: Baseline target: ${TARGET_BASELINE} "
50
- echo " INFO: Tests target: ${TARGET_TESTS} "
61
+ echo " INFO: Test target: ${TARGET_TESTS} "
51
62
echo " INFO: Output directory: ${OUTPUT_DIR} "
52
63
53
64
readonly WORKSPACE=$( cd " $( dirname " $( readlink -f " ${0} " ) " ) " && bazel info workspace)
54
65
55
- function run_baseline() {
56
- echo " \nINFO: Build baseline"
57
- echo " Baseline target: ${TARGET_BASELINE} "
66
+ run_baseline () {
67
+ echo -e " \nINFO: Building baseline target: ${TARGET_BASELINE} "
58
68
bazel build \
59
69
--collect_code_coverage \
60
70
--experimental_fetch_all_coverage_outputs \
61
- -- ${TARGET_BASELINE}
71
+ --cxxopt=" -O0" \
72
+ -- " ${TARGET_BASELINE} "
62
73
}
63
74
64
- function run_coverage_tests() {
65
- echo " \nINFO: Run test"
66
- echo " Test target: ${TARGET_TESTS} "
75
+ run_coverage_tests () {
76
+ echo -e " \nINFO: Running test target: ${TARGET_TESTS} "
67
77
bazel coverage \
68
78
--nocache_test_results \
69
79
--experimental_fetch_all_coverage_outputs \
70
80
--cxxopt=" -O0" \
71
- -- ${TARGET_TESTS}
81
+ -- " ${TARGET_TESTS} "
72
82
}
73
83
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
84
+ delete_coverage_files () {
85
+ echo -e " \nINFO: Cleaning old .gcno and .gcda files"
86
+ local directories=(" ${GCNO_DIR} " " ${GCDA_DIR} " " ${FILTERED_GCNO_DIR} " " ${FILTERED_GCDA_DIR} " )
87
+ for dir in " ${directories[@]} " ; do
88
+ find " $dir " -name " *.gcno" -exec chmod +w {} \; || true
89
+ find " $dir " -name " *.gcda" -exec chmod +w {} \; || true
90
+ find " $dir " -name " *.gcno" -exec rm -f {} \; || true
91
+ find " $dir " -name " *.gcda" -exec rm -f {} \; || true
92
+ done
81
93
}
82
94
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 {} \;
95
+ generate_hashed_name () {
96
+ local file_path=" $1 "
97
+ local extension=" ${file_path##* .} "
98
+ local path_no_extension=" ${file_path% .$extension } "
99
+ local path_in_bin=$( echo " $path_no_extension " | awk -F" bin" " {print substr(\$ 0, length(\$ 1\" bin\" ) + 1)}" )
100
+ local hash=$( echo -n " $path_in_bin " | sha256sum | awk " {print \$ 1}" )
101
+ echo " $hash .$extension "
88
102
}
89
103
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 "
104
+ copy_coverage_files () {
105
+ echo -e " \nINFO: Copy hashed .gcno and .gcda files"
106
+ echo " Input directory: $1 "
107
+ echo " Output dir: $2 "
95
108
echo " Exclude pattern: $EXCLUDE_PATTERN "
96
109
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
110
+ mkdir -p " $2 "
102
111
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 "
112
+ find " $1 " -type f \( - name " *.gcda " -o -name " *. gcno" \) ! -path " */external/* " ! -path " *gtest* " | while IFS= read -r file; do
113
+ new_name=$( generate_hashed_name " $file " " $1 " )
114
+ cp " $file " " $2 /$new_name "
115
+ echo " Copied: $file -> $2 /$new_name "
107
116
done
108
117
}
109
118
110
- function calculate_coverage() {
111
- echo " \nINFO: Generate coverage data"
112
- echo " Output directory: $OUTPUT_DIR "
113
- lcov --directory " $TARGET_DIR " \
114
- --capture \
115
- --ignore-errors source \
116
- --output-file " ${OUTPUT_DIR} /coverage.info"
117
- lcov --remove " ${OUTPUT_DIR} /coverage.info" \
119
+ main () {
120
+ pushd " ${WORKSPACE} " || return
121
+
122
+ bazel clean
123
+ delete_coverage_files
124
+ run_baseline
125
+ copy_coverage_files " ${GCNO_DIR} " " ${FILTERED_GCNO_DIR} "
126
+
127
+ echo -e " \nINFO: Create baseline.info"
128
+ lcov \
129
+ --directory " ${FILTERED_GCNO_DIR} " \
130
+ -c \
131
+ -i \
132
+ --output-file " ${OUTPUT_DIR} /baseline.info"
133
+
134
+ echo -e " \nINFO: Filter baseline.info"
135
+ lcov \
136
+ --directory " ${FILTERED_GCNO_DIR} " \
137
+ --remove " ${OUTPUT_DIR} /baseline.info" \
138
+ ' /usr/*' \
139
+ ' *external/*' \
140
+ ' *gtest*' \
141
+ --ignore-errors unused \
142
+ --ignore-errors empty \
143
+ --output-file " ${OUTPUT_DIR} /baseline_filtered.info"
144
+ sed -i ' s|/proc/self/cwd/||g' " ${OUTPUT_DIR} /baseline_filtered.info"
145
+
146
+ run_coverage_tests
147
+ copy_coverage_files " ${GCDA_DIR} " " ${FILTERED_GCDA_DIR} "
148
+
149
+ echo -e " \nINFO: Create tests.info"
150
+ lcov \
151
+ --directory " ${FILTERED_GCDA_DIR} " \
152
+ -c \
153
+ --output-file " ${OUTPUT_DIR} /tests.info"
154
+
155
+ echo -e " \nINFO: Filter tests.info"
156
+ lcov \
157
+ --directory " ${FILTERED_GCDA_DIR} " \
158
+ --remove " ${OUTPUT_DIR} /tests.info" \
118
159
' /usr/*' \
119
160
' external/*' \
120
161
' *gtest*' \
121
162
--ignore-errors unused \
122
- --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
163
+ --output-file " ${OUTPUT_DIR} /tests_filtered.info"
164
+ sed -i ' s|/proc/self/cwd/||g' " ${OUTPUT_DIR} /tests_filtered.info"
165
+
166
+ echo -e " \nINFO: Merge baseline and tests coverage report"
167
+ lcov -a " ${OUTPUT_DIR} /baseline_filtered.info" \
168
+ -a " ${OUTPUT_DIR} /tests_filtered.info" \
169
+ -o " ${OUTPUT_DIR} /coverage.info"
125
170
126
171
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 "
172
+ echo -e " \nINFO: Generating HTML coverage report"
173
+ genhtml " ${OUTPUT_DIR} /coverage.info" \
174
+ --output-directory " ${OUTPUT_DIR} "
131
175
else
132
- echo " \nINFO: Generate coverage summary"
133
- lcov --summary " ${OUTPUT_DIR} /coverage_filtered .info"
176
+ echo -e " \nINFO: Generating coverage summary"
177
+ lcov --summary " ${OUTPUT_DIR} /coverage .info"
134
178
fi
135
- }
136
179
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
180
popd || return
145
181
}
146
182
0 commit comments