@@ -70,6 +70,7 @@ function set_up() {
7070
7171 # Create the CC sources.
7272 mkdir -p " $ROOT_VAR /coverage_srcs/"
73+ mkdir -p " $ROOT_VAR /coverage_srcs/different"
7374 cat << EOF > "$ROOT_VAR /coverage_srcs/a.h"
7475int a(bool what);
7576EOF
@@ -85,6 +86,20 @@ int a(bool what) {
8586 return b(-1);
8687 }
8788}
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+ }
88103EOF
89104
90105 cat << EOF > "$ROOT_VAR /coverage_srcs/b.h"
@@ -100,37 +115,24 @@ EOF
100115 cat << EOF > "$ROOT_VAR /coverage_srcs/t.cc"
101116#include <stdio.h>
102117#include "a.h"
118+ #include "different/a.h"
103119
104120int main(void) {
105121 a(true);
122+ different_a(false);
106123}
107124EOF
108125
109126 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+
131131 agcno=$( ls coverage_srcs/* a.gcno)
132+ dagcno=$( ls coverage_srcs/different/* a.gcno)
132133 tgcno=$( ls coverage_srcs/* t.gcno)
133134 agcda=$( ls coverage_srcs/* a.gcda)
135+ dagcda=$( ls coverage_srcs/different/* a.gcda)
134136 tgcda=$( ls coverage_srcs/* t.gcda)
135137 # Even though gcov expects the gcda files to be next to the gcno files,
136138 # during Bazel execution this will not be the case. collect_cc_coverage.sh
@@ -140,32 +142,41 @@ EOF
140142 # https://github.com/bazelbuild/bazel/issues/16229
141143 mv $agcda " $COVERAGE_DIR_VAR /$agcda "
142144 mv $tgcda " $COVERAGE_DIR_VAR /$tgcda "
145+ mkdir " $COVERAGE_DIR_VAR /$( dirname ${dagcda} ) "
146+ mv $dagcda " $COVERAGE_DIR_VAR /$dagcda "
143147
144148 # All generated .gcno files need to be in the manifest otherwise
145149 # the coverage report will be incomplete.
146150 echo " $tgcno " >> " $COVERAGE_MANIFEST_VAR "
147151 echo " $agcno " >> " $COVERAGE_MANIFEST_VAR "
152+ echo " $dagcno " >> " $COVERAGE_MANIFEST_VAR "
148153}
149154
150155# Generates and executes an instrumented binary:
151156#
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.
155160#
156161# Executes the instrumented binary. This step also generates the
157162# profile data (.gcda) files.
163+ #
164+ # - [(source_file, object_file),...] - source files and object file paths
158165# - path_to_binary destination of the binary produced by g++
159166function generate_and_execute_instrumented_binary() {
160167 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
169180 " $path_to_binary " || fail " Couldn't execute the instrumented binary \
170181 $path_to_binary "
171182}
@@ -223,11 +234,12 @@ function assert_gcov_coverage_srcs_t_cc() {
223234 local output_file=" ${1} " ; shift
224235
225236 # 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
229239lcount:5,1
230- lcount:6,1"
240+ lcount:6,1
241+ lcount:7,1
242+ lcount:8,1"
231243 assert_coverage_entry_in_file " $expected_gcov_result_t_cc " " $output_file "
232244}
233245
@@ -244,6 +256,19 @@ lcount:5,0"
244256 assert_coverage_entry_in_file " $expected_gcov_result " " $output_file "
245257}
246258
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+
247272function assert_gcov_coverage_srcs_a_cc_json() {
248273 local output_file=" ${1} " ; shift
249274
@@ -265,7 +290,7 @@ function assert_gcov_coverage_srcs_t_cc_json() {
265290
266291 # The expected coverage result for coverage_srcs/t.cc in gcov format.
267292 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"}
269294EOF
270295 local expected_gcov_result_t_cc=$( cat expected_gcov_result_t_cc | tr -d ' \n' )
271296 assert_coverage_entry_in_file " $expected_gcov_result_t_cc " " $output_file "
@@ -274,14 +299,24 @@ EOF
274299function assert_gcov_coverage_srcs_b_h_json() {
275300 local output_file=" ${1} " ; shift
276301
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.
278303 cat > expected_gcov_result_b_h << EOF
279304{"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"}
280305EOF
281306 local expected_gcov_result_b_h=$( cat expected_gcov_result_b_h | tr -d ' \n' )
282307 assert_coverage_entry_in_file " $expected_gcov_result_b_h " " $output_file "
283308}
284309
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+ }
285320
286321function test_cc_test_coverage_gcov() {
287322 local -r gcov_location=$( which gcov)
@@ -303,9 +338,6 @@ function test_cc_test_coverage_gcov() {
303338 # Location of the output file of the C++ coverage script when gcov is used.
304339 local output_file=" $COVERAGE_DIR_VAR /_cc_coverage.gcov"
305340
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-
309341 # If the file _cc_coverge.gcov does not exist, it means we are using gcc 9
310342 # or higher which uses json.gz files as intermediate format. We will keep
311343 # testing gcc 7 and 8 until most users have migrated.
@@ -319,35 +351,40 @@ function test_cc_test_coverage_gcov() {
319351 assert_gcov_coverage_srcs_a_cc " $output_file "
320352 assert_gcov_coverage_srcs_t_cc " $output_file "
321353 assert_gcov_coverage_srcs_b_h " $output_file "
354+ assert_gcov_coverage_srcs_d_a_cc " $output_file "
322355
323356 # This assertion is needed to make sure no other source files are included
324357 # in the output file.
325358 local nr_lines=" $( wc -l < " $output_file " ) "
326- [[ " $nr_lines " == 17 ]] || \
359+ [[ " $nr_lines " == 24 ]] || \
327360 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 "
329362 else
363+
330364 # There may or may not be "gcda" in the extension.
331365 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=$?
333367 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)
336371 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)
339375 fi
340376 output_file_json=" output_file.json"
341- zcat $agcda $tgcda > $output_file_json
377+ zcat $agcda $tgcda $dagcda > $output_file_json
342378
343379 assert_gcov_coverage_srcs_a_cc_json " $output_file_json "
344380 assert_gcov_coverage_srcs_t_cc_json " $output_file_json "
345381 assert_gcov_coverage_srcs_b_h_json " $output_file_json "
382+ assert_gcov_coverage_srcs_d_a_cc_json " $output_file_json "
346383
347384 local nr_files=" $( grep -o -i " \" file\" :" " $output_file_json " | wc -l) "
348- [[ " $nr_files " == 3 ]] || \
385+ [[ " $nr_files " == 4 ]] || \
349386 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 "
351388 fi
352389}
353390
0 commit comments