@@ -70,6 +70,7 @@ function set_up() {
70
70
71
71
# Create the CC sources.
72
72
mkdir -p " $ROOT_VAR /coverage_srcs/"
73
+ mkdir -p " $ROOT_VAR /coverage_srcs/different"
73
74
cat << EOF > "$ROOT_VAR /coverage_srcs/a.h"
74
75
int a(bool what);
75
76
EOF
@@ -85,6 +86,20 @@ int a(bool what) {
85
86
return b(-1);
86
87
}
87
88
}
89
+ EOF
90
+
91
+ cat << EOF > "$ROOT_VAR /coverage_srcs/different/a.h"
92
+ int different_a(bool what);
93
+ EOF
94
+
95
+ cat << EOF > "$ROOT_VAR /coverage_srcs/different/a.cc"
96
+ int different_a(bool what) {
97
+ if (what) {
98
+ return 1;
99
+ } else {
100
+ return 2;
101
+ }
102
+ }
88
103
EOF
89
104
90
105
cat << EOF > "$ROOT_VAR /coverage_srcs/b.h"
@@ -100,37 +115,24 @@ EOF
100
115
cat << EOF > "$ROOT_VAR /coverage_srcs/t.cc"
101
116
#include <stdio.h>
102
117
#include "a.h"
118
+ #include "different/a.h"
103
119
104
120
int main(void) {
105
121
a(true);
122
+ different_a(false);
106
123
}
107
124
EOF
108
125
109
126
generate_and_execute_instrumented_binary coverage_srcs/test \
110
- coverage_srcs/a.h coverage_srcs/a.cc \
111
- coverage_srcs/b.h \
112
- coverage_srcs/t.cc
113
-
114
- # Prior to version 11, g++ generates the notes files in the current directory
115
- # instead of next to the object file despite the documentation indicating otherwise:
116
- # https://gcc.gnu.org/onlinedocs/gcc/Gcov-Data-Files.html#Gcov-Data-Files
117
- # This is fixed in g++ 11 so we have to handle both cases.
118
-
119
- local not_found=0
120
- ls coverage_srcs/* a.gcno > /dev/null 2>&1 || not_found=$?
121
- if [[ $not_found -ne 0 ]]; then
122
- agcno=$( ls * a.gcno)
123
- tgcno=$( ls * t.gcno)
124
- agcda=$( ls * a.gcda)
125
- tgcda=$( ls * t.gcda)
126
- mv $agcno coverage_srcs/$agcno
127
- mv $tgcno coverage_srcs/$tgcno
128
- mv $agcda coverage_srcs/$agcda
129
- mv $tgcda coverage_srcs/$tgcda
130
- fi
127
+ coverage_srcs/a.cc coverage_srcs/a.o \
128
+ coverage_srcs/different/a.cc coverage_srcs/different/a.o \
129
+ coverage_srcs/t.cc coverage_srcs/t.o
130
+
131
131
agcno=$( ls coverage_srcs/* a.gcno)
132
+ dagcno=$( ls coverage_srcs/different/* a.gcno)
132
133
tgcno=$( ls coverage_srcs/* t.gcno)
133
134
agcda=$( ls coverage_srcs/* a.gcda)
135
+ dagcda=$( ls coverage_srcs/different/* a.gcda)
134
136
tgcda=$( ls coverage_srcs/* t.gcda)
135
137
# Even though gcov expects the gcda files to be next to the gcno files,
136
138
# during Bazel execution this will not be the case. collect_cc_coverage.sh
@@ -140,32 +142,41 @@ EOF
140
142
# https://github.com/bazelbuild/bazel/issues/16229
141
143
mv $agcda " $COVERAGE_DIR_VAR /$agcda "
142
144
mv $tgcda " $COVERAGE_DIR_VAR /$tgcda "
145
+ mkdir " $COVERAGE_DIR_VAR /$( dirname ${dagcda} ) "
146
+ mv $dagcda " $COVERAGE_DIR_VAR /$dagcda "
143
147
144
148
# All generated .gcno files need to be in the manifest otherwise
145
149
# the coverage report will be incomplete.
146
150
echo " $tgcno " >> " $COVERAGE_MANIFEST_VAR "
147
151
echo " $agcno " >> " $COVERAGE_MANIFEST_VAR "
152
+ echo " $dagcno " >> " $COVERAGE_MANIFEST_VAR "
148
153
}
149
154
150
155
# Generates and executes an instrumented binary:
151
156
#
152
- # Reads the list of arguments provided by the caller (using $@) and uses them
153
- # to produce an instrumented binary using g++. This step also generates
154
- # the notes (.gcno) files.
157
+ # Reads the list of source files along with object files paths. Uses them
158
+ # to produce object files and link them to an instrumented binary using g++.
159
+ # This step also generates the notes (.gcno) files.
155
160
#
156
161
# Executes the instrumented binary. This step also generates the
157
162
# profile data (.gcda) files.
163
+ #
164
+ # - [(source_file, object_file),...] - source files and object file paths
158
165
# - path_to_binary destination of the binary produced by g++
159
166
function generate_and_execute_instrumented_binary() {
160
167
local path_to_binary=" ${1} " ; shift
161
- g++ -coverage \
162
- " $@ " -o " $path_to_binary " \
163
- || fail " Couldn't produce the instrumented binary for $@ \
164
- with path_to_binary $path_to_binary "
165
-
166
- # Execute the instrumented binary and generates the profile data (.gcda)
167
- # file.
168
- # The profile data file is placed in $gcda_directory.
168
+ local src_file=" "
169
+ local obj_file=" "
170
+ local obj_files=" "
171
+ while [[ $# -ge 2 ]]; do
172
+ src_file=$1 ; shift
173
+ obj_file=$1 ; shift
174
+ obj_files=" ${obj_files} $obj_file "
175
+ g++ -coverage -fprofile-arcs -ftest-coverage -lgcov -c \
176
+ " $src_file " -o " $obj_file "
177
+ done
178
+
179
+ g++ -coverage -fprofile-arcs -ftest-coverage -lgcov -o " $path_to_binary " $obj_files
169
180
" $path_to_binary " || fail " Couldn't execute the instrumented binary \
170
181
$path_to_binary "
171
182
}
@@ -223,11 +234,12 @@ function assert_gcov_coverage_srcs_t_cc() {
223
234
local output_file=" ${1} " ; shift
224
235
225
236
# The expected coverage result for coverage_srcs/t.cc in gcov format.
226
- local expected_gcov_result_t_cc=" file:coverage_srcs/t.cc
227
- function:4,1,main
228
- lcount:4,1
237
+ local expected_gcov_result_t_cc=" coverage_srcs/t.cc
238
+ function:5,1,main
229
239
lcount:5,1
230
- lcount:6,1"
240
+ lcount:6,1
241
+ lcount:7,1
242
+ lcount:8,1"
231
243
assert_coverage_entry_in_file " $expected_gcov_result_t_cc " " $output_file "
232
244
}
233
245
@@ -244,6 +256,19 @@ lcount:5,0"
244
256
assert_coverage_entry_in_file " $expected_gcov_result " " $output_file "
245
257
}
246
258
259
+ function assert_gcov_coverage_srcs_d_a_cc() {
260
+ local output_file=" ${1} " ; shift
261
+
262
+ # The expected coverage result for coverage_srcs/different/a.cc in gcov format.
263
+ local expected_gcov_result_d_a_cc=" file:coverage_srcs/different/a.cc
264
+ function:1,1,_Z11different_ab
265
+ lcount:1,1
266
+ lcount:2,1
267
+ lcount:3,0
268
+ lcount:5,1"
269
+ assert_coverage_entry_in_file " $expected_gcov_result_d_a_cc " " $output_file "
270
+ }
271
+
247
272
function assert_gcov_coverage_srcs_a_cc_json() {
248
273
local output_file=" ${1} " ; shift
249
274
@@ -265,7 +290,7 @@ function assert_gcov_coverage_srcs_t_cc_json() {
265
290
266
291
# The expected coverage result for coverage_srcs/t.cc in gcov format.
267
292
cat > expected_gcov_result_t_cc << EOF
268
- {"lines": [{"branches": [], "count": 1, "line_number": 4 , "unexecuted_block": false, "function_name": "main"}, {"branches": [], "count": 1, "line_number": 5 , "unexecuted_block": false, "function_name": "main"}, {"branches": [], "count": 1, "line_number": 6 , "unexecuted_block": false, "function_name": "main"}], "functions": [{"blocks": 3 , "end_column": 1, "start_line": 4 , "name": "main", "blocks_executed": 3 , "execution_count": 1, "demangled_name": "main", "start_column": 5, "end_line": 6 }], "file": "coverage_srcs/t.cc"}
293
+ {"lines": [{"branches": [], "count": 1, "line_number": 5 , "unexecuted_block": false, "function_name": "main"}, {"branches": [], "count": 1, "line_number": 6 , "unexecuted_block": false, "function_name": "main"}, {"branches": [], "count": 1, "line_number": 7 , "unexecuted_block": false, "function_name": "main"}, {"branches": [ ], "count": 1, "line_number": 8, "unexecuted_block": false, "function_name": "main"}], " functions": [{"blocks": 4 , "end_column": 1, "start_line": 5 , "name": "main", "blocks_executed": 4 , "execution_count": 1, "demangled_name": "main", "start_column": 5, "end_line": 8 }], "file": "coverage_srcs/t.cc"}
269
294
EOF
270
295
local expected_gcov_result_t_cc=$( cat expected_gcov_result_t_cc | tr -d ' \n' )
271
296
assert_coverage_entry_in_file " $expected_gcov_result_t_cc " " $output_file "
@@ -274,14 +299,24 @@ EOF
274
299
function assert_gcov_coverage_srcs_b_h_json() {
275
300
local output_file=" ${1} " ; shift
276
301
277
- # The expected coverage result for coverage_srcs/t.cc in gcov format.
302
+ # The expected coverage result for coverage_srcs/b.h in gcov format.
278
303
cat > expected_gcov_result_b_h << EOF
279
304
{"lines": [{"branches": [], "count": 1, "line_number": 1, "unexecuted_block": false, "function_name": "_Z1bi"}, {"branches": [], "count": 1, "line_number": 2, "unexecuted_block": false, "function_name": "_Z1bi"}, {"branches": [], "count": 1, "line_number": 3, "unexecuted_block": false, "function_name": "_Z1bi"}, {"branches": [], "count": 0, "line_number": 5, "unexecuted_block": true, "function_name": "_Z1bi"}], "functions": [{"blocks": 4, "end_column": 1, "start_line": 1, "name": "_Z1bi", "blocks_executed": 3, "execution_count": 1, "demangled_name": "b(int)", "start_column": 5, "end_line": 7}], "file": "coverage_srcs/b.h"}
280
305
EOF
281
306
local expected_gcov_result_b_h=$( cat expected_gcov_result_b_h | tr -d ' \n' )
282
307
assert_coverage_entry_in_file " $expected_gcov_result_b_h " " $output_file "
283
308
}
284
309
310
+ function assert_gcov_coverage_srcs_d_a_cc_json() {
311
+ local output_file=" ${1} " ; shift
312
+
313
+ # The expected coverage result for coverage_srcs/different/a.cc in gcov format.
314
+ cat > expected_gcov_result_d_a_cc << EOF
315
+ {"lines": [{"branches": [], "count": 1, "line_number": 1, "unexecuted_block": false, "function_name": "_Z11different_ab"}, {"branches": [], "count": 1, "line_number": 2, "unexecuted_block": false, "function_name": "_Z11different_ab"}, {"branches": [], "count": 0, "line_number": 3, "unexecuted_block": true, "function_name": "_Z11different_ab"}, {"branches": [], "count": 1, "line_number": 5, "unexecuted_block": false, "function_name": "_Z11different_ab"}], "functions": [{"blocks": 4, "end_column": 1, "start_line": 1, "name": "_Z11different_ab", "blocks_executed": 3, "execution_count": 1, "demangled_name": "different_a(bool)", "start_column": 5, "end_line": 7}], "file": "coverage_srcs/different/a.cc"}
316
+ EOF
317
+ local expected_gcov_result_d_a_cc=$( cat expected_gcov_result_d_a_cc | tr -d ' \n' )
318
+ assert_coverage_entry_in_file " $expected_gcov_result_d_a_cc " " $output_file "
319
+ }
285
320
286
321
function test_cc_test_coverage_gcov() {
287
322
local -r gcov_location=$( which gcov)
@@ -303,9 +338,6 @@ function test_cc_test_coverage_gcov() {
303
338
# Location of the output file of the C++ coverage script when gcov is used.
304
339
local output_file=" $COVERAGE_DIR_VAR /_cc_coverage.gcov"
305
340
306
- # Location of the output file of the C++ coverage script when gcov is used.
307
- local output_file=" $COVERAGE_DIR_VAR /_cc_coverage.gcov"
308
-
309
341
# If the file _cc_coverge.gcov does not exist, it means we are using gcc 9
310
342
# or higher which uses json.gz files as intermediate format. We will keep
311
343
# testing gcc 7 and 8 until most users have migrated.
@@ -319,35 +351,40 @@ function test_cc_test_coverage_gcov() {
319
351
assert_gcov_coverage_srcs_a_cc " $output_file "
320
352
assert_gcov_coverage_srcs_t_cc " $output_file "
321
353
assert_gcov_coverage_srcs_b_h " $output_file "
354
+ assert_gcov_coverage_srcs_d_a_cc " $output_file "
322
355
323
356
# This assertion is needed to make sure no other source files are included
324
357
# in the output file.
325
358
local nr_lines=" $( wc -l < " $output_file " ) "
326
- [[ " $nr_lines " == 17 ]] || \
359
+ [[ " $nr_lines " == 24 ]] || \
327
360
fail " Number of lines in C++ gcov coverage output file is " \
328
- " $nr_lines and different than 17 "
361
+ " $nr_lines and different than 24 "
329
362
else
363
+
330
364
# There may or may not be "gcda" in the extension.
331
365
local not_found=0
332
- ls $COVERAGE_DIR_VAR /* .gcda.gcov.json.gz > /dev/null 2>&1 || not_found=$?
366
+ ls $COVERAGE_DIR_VAR /coverage_srcs/ * .gcda.gcov.json.gz > /dev/null 2>&1 || not_found=$?
333
367
if [[ $not_found -ne 0 ]]; then
334
- agcda=$( ls $COVERAGE_DIR_VAR /* a.gcov.json.gz)
335
- tgcda=$( ls $COVERAGE_DIR_VAR /* t.gcov.json.gz)
368
+ agcda=$( ls $COVERAGE_DIR_VAR /coverage_srcs/* a.gcov.json.gz)
369
+ tgcda=$( ls $COVERAGE_DIR_VAR /coverage_srcs/* t.gcov.json.gz)
370
+ dagcda=$( ls $COVERAGE_DIR_VAR /coverage_srcs/different/* a.gcov.json.gz)
336
371
else
337
- agcda=$( ls $COVERAGE_DIR_VAR /* a.gcda.gcov.json.gz)
338
- tgcda=$( ls $COVERAGE_DIR_VAR /* t.gcda.gcov.json.gz)
372
+ agcda=$( ls $COVERAGE_DIR_VAR /coverage_srcs/* a.gcda.gcov.json.gz)
373
+ tgcda=$( ls $COVERAGE_DIR_VAR /coverage_srcs/* t.gcda.gcov.json.gz)
374
+ dagcda=$( ls $COVERAGE_DIR_VAR /coverage_srcs/different/* a.gcda.gcov.json.gz)
339
375
fi
340
376
output_file_json=" output_file.json"
341
- zcat $agcda $tgcda > $output_file_json
377
+ zcat $agcda $tgcda $dagcda > $output_file_json
342
378
343
379
assert_gcov_coverage_srcs_a_cc_json " $output_file_json "
344
380
assert_gcov_coverage_srcs_t_cc_json " $output_file_json "
345
381
assert_gcov_coverage_srcs_b_h_json " $output_file_json "
382
+ assert_gcov_coverage_srcs_d_a_cc_json " $output_file_json "
346
383
347
384
local nr_files=" $( grep -o -i " \" file\" :" " $output_file_json " | wc -l) "
348
- [[ " $nr_files " == 3 ]] || \
385
+ [[ " $nr_files " == 4 ]] || \
349
386
fail " Number of files in C++ gcov coverage output file is " \
350
- " $nr_files and different than 3 "
387
+ " $nr_files and different than 4 "
351
388
fi
352
389
}
353
390
0 commit comments