@@ -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,151 @@ 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
+ --instrumentation_filter=" [/:]" \
82
+ -- " ${TARGET_TESTS} "
72
83
}
73
84
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
85
+ delete_coverage_files () {
86
+ echo -e " \nINFO: Cleaning old .gcno and .gcda files"
87
+ local directories=(" ${GCNO_DIR} " " ${GCDA_DIR} " " ${FILTERED_GCNO_DIR} " " ${FILTERED_GCDA_DIR} " )
88
+ for dir in " ${directories[@]} " ; do
89
+ find " $dir " -name " *.gcno" -exec chmod +w {} \; || true
90
+ find " $dir " -name " *.gcda" -exec chmod +w {} \; || true
91
+ find " $dir " -name " *.gcno" -exec rm -f {} \; || true
92
+ find " $dir " -name " *.gcda" -exec rm -f {} \; || true
93
+ done
81
94
}
82
95
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 {} \;
96
+ generate_hashed_name () {
97
+ local file_path=" $1 "
98
+ local extension=" ${file_path##* .} "
99
+ local path_no_extension=" ${file_path% .$extension } "
100
+ local path_in_bin=$( echo " $path_no_extension " | awk -F" bin" " {print substr(\$ 0, length(\$ 1\" bin\" ) + 1)}" )
101
+ local hash=$( echo -n " $path_in_bin " | sha256sum | awk " {print \$ 1}" )
102
+ echo " $hash .$extension "
88
103
}
89
104
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 "
105
+ copy_coverage_files () {
106
+ echo -e " \nINFO: Copy hashed .gcno and .gcda files"
107
+ echo " Input directory: $1 "
108
+ echo " Output dir: $2 "
95
109
echo " Exclude pattern: $EXCLUDE_PATTERN "
96
110
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
111
+ mkdir -p " $2 "
102
112
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 "
113
+ find " $1 " -type f \( - name " *.gcda " -o -name " *. gcno" \) ! -path " */external/* " ! -path " *gtest* " ! -path " *test* " | while IFS= read -r file; do
114
+ new_name=$( generate_hashed_name " $file " " $1 " )
115
+ cp " $file " " $2 /$new_name "
116
+ echo " Copied: $file -> $2 /$new_name "
107
117
done
108
118
}
109
119
110
- function calculate_coverage() {
111
- echo " \nINFO: Generate coverage data"
112
- echo " Output directory: $OUTPUT_DIR "
113
- lcov --directory " $TARGET_DIR " \
120
+ main () {
121
+ pushd " ${WORKSPACE} " || return
122
+
123
+ bazel clean
124
+ delete_coverage_files
125
+ run_baseline
126
+ # copy_coverage_files "${GCNO_DIR}" "${FILTERED_GCNO_DIR}"
127
+ FILTERED_GCNO_DIR=" ${GCNO_DIR} "
128
+ FILTERED_GCDA_DIR=" ${GCDA_DIR} "
129
+
130
+ echo -e " \nINFO: Create baseline.info"
131
+ lcov \
132
+ --directory " ${FILTERED_GCNO_DIR} " \
133
+ --capture \
134
+ -i \
135
+ --output-file " ${OUTPUT_DIR} /baseline.info"
136
+
137
+ echo -e " \nINFO: Filter baseline.info"
138
+ lcov \
139
+ --directory " ${FILTERED_GCNO_DIR} " \
140
+ --remove " ${OUTPUT_DIR} /baseline.info" \
141
+ ' /usr/*' \
142
+ ' *external/*' \
143
+ ' *gtest*' \
144
+ --ignore-errors unused \
145
+ --ignore-errors empty \
146
+ --output-file " ${OUTPUT_DIR} /baseline_filtered.info"
147
+ sed -i ' s|/proc/self/cwd/||g' " ${OUTPUT_DIR} /baseline_filtered.info"
148
+
149
+ run_coverage_tests
150
+ # copy_coverage_files "${GCDA_DIR}" "${FILTERED_GCDA_DIR}"
151
+
152
+ echo -e " \nINFO: Create tests.info"
153
+ lcov \
154
+ --directory " ${FILTERED_GCDA_DIR} " \
114
155
--capture \
115
156
--ignore-errors source \
116
- --output-file " ${OUTPUT_DIR} /coverage.info"
117
- lcov --remove " ${OUTPUT_DIR} /coverage.info" \
157
+ --output-file " ${OUTPUT_DIR} /tests.info"
158
+
159
+ echo -e " \nINFO: Filter tests.info"
160
+ lcov \
161
+ --directory " ${FILTERED_GCDA_DIR} " \
162
+ --remove " ${OUTPUT_DIR} /tests.info" \
118
163
' /usr/*' \
119
164
' external/*' \
120
165
' *gtest*' \
121
166
--ignore-errors unused \
122
167
--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
168
+ --output-file " ${OUTPUT_DIR} /tests_filtered.info"
169
+ sed -i ' s|/proc/self/cwd/||g' " ${OUTPUT_DIR} /tests_filtered.info"
170
+
171
+ echo -e " \nINFO: Merge baseline and tests coverage report"
172
+ lcov \
173
+ -a " ${OUTPUT_DIR} /baseline_filtered.info" \
174
+ -a " ${OUTPUT_DIR} /tests_filtered.info" \
175
+ -o " ${OUTPUT_DIR} /coverage.info"
125
176
126
177
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 "
178
+ echo -e " \nINFO: Generating HTML coverage report"
179
+ genhtml " ${OUTPUT_DIR} /coverage.info" \
180
+ --output-directory " ${OUTPUT_DIR} "
131
181
else
132
- echo " \nINFO: Generate coverage summary"
133
- lcov --summary " ${OUTPUT_DIR} /coverage_filtered .info"
182
+ echo -e " \nINFO: Generating coverage summary"
183
+ lcov --summary " ${OUTPUT_DIR} /coverage .info"
134
184
fi
135
- }
136
185
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
186
popd || return
145
187
}
146
188
0 commit comments