From 2ca1ab2c2c73d78021794f3099ee892cc73f515e Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Mon, 12 Sep 2022 16:47:14 +0200 Subject: [PATCH] Make bazel_cc_code_coverage_test more robust against GCC version differences (#16254) * -fprofile-dir shouldn't be used because on the g++ command line because it has different behaviour with different versions (w.r.t. where the output gcda file ends up). * The gcda and gcno files may end up in the same directory as the object file or in the current working directory. * The output of the gcov call in collect_cc_coverage may be "*.gcda.gcov.json.gz" or "*.gcov.json.gz" (as well as the original text file for much older GCC versions). Also re-enable the test for Ubuntu 20.04 pre and postsubmits. Fixes #16229 Closes #16235. PiperOrigin-RevId: 473218955 Change-Id: I1f4887f251da8f56f8ea525c1a1410e6257bf31b Co-authored-by: Charles Mita --- .../bazel/bazel_cc_code_coverage_test.sh | 69 ++++++++++++------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/src/test/shell/bazel/bazel_cc_code_coverage_test.sh b/src/test/shell/bazel/bazel_cc_code_coverage_test.sh index 66d2327063cd23..3748bae5cbc57f 100755 --- a/src/test/shell/bazel/bazel_cc_code_coverage_test.sh +++ b/src/test/shell/bazel/bazel_cc_code_coverage_test.sh @@ -107,24 +107,44 @@ int main(void) { EOF generate_and_execute_instrumented_binary coverage_srcs/test \ - "$COVERAGE_DIR_VAR/coverage_srcs" \ coverage_srcs/a.h coverage_srcs/a.cc \ coverage_srcs/b.h \ coverage_srcs/t.cc - # g++ generates the notes files in the current directory. The documentation - # (https://gcc.gnu.org/onlinedocs/gcc/Gcov-Data-Files.html#Gcov-Data-Files) - # says they are placed in the same directory as the object file, but they - # are not. Therefore we move them in the same directory. - agcno=$(ls *a.gcno) - tgcno=$(ls *t.gcno) - mv $agcno coverage_srcs/$agcno - mv $tgcno coverage_srcs/$tgcno + # Prior to version 11, g++ generates the notes files in the current directory + # instead of next to the object file despite the documentation indicating otherwise: + # https://gcc.gnu.org/onlinedocs/gcc/Gcov-Data-Files.html#Gcov-Data-Files + # This is fixed in g++ 11 so we have to handle both cases. + + local not_found=0 + ls coverage_srcs/*a.gcno > /dev/null 2>&1 || not_found=$? + if [[ $not_found -ne 0 ]]; then + agcno=$(ls *a.gcno) + tgcno=$(ls *t.gcno) + agcda=$(ls *a.gcda) + tgcda=$(ls *t.gcda) + mv $agcno coverage_srcs/$agcno + mv $tgcno coverage_srcs/$tgcno + mv $agcda coverage_srcs/$agcda + mv $tgcda coverage_srcs/$tgcda + fi + agcno=$(ls coverage_srcs/*a.gcno) + tgcno=$(ls coverage_srcs/*t.gcno) + agcda=$(ls coverage_srcs/*a.gcda) + tgcda=$(ls coverage_srcs/*t.gcda) + # Even though gcov expects the gcda files to be next to the gcno files, + # during Bazel execution this will not be the case. collect_cc_coverage.sh + # expects them to be in the COVERAGE_DIR and will move the gcno files itself. + # We cannot use -fprofile-dir during compilation because this causes the + # filenames to undergo mangling; see + # https://github.com/bazelbuild/bazel/issues/16229 + mv $agcda "$COVERAGE_DIR_VAR/$agcda" + mv $tgcda "$COVERAGE_DIR_VAR/$tgcda" # All generated .gcno files need to be in the manifest otherwise # the coverage report will be incomplete. - echo "coverage_srcs/$tgcno" >> "$COVERAGE_MANIFEST_VAR" - echo "coverage_srcs/$agcno" >> "$COVERAGE_MANIFEST_VAR" + echo "$tgcno" >> "$COVERAGE_MANIFEST_VAR" + echo "$agcno" >> "$COVERAGE_MANIFEST_VAR" } # Generates and executes an instrumented binary: @@ -138,17 +158,7 @@ EOF # - path_to_binary destination of the binary produced by g++ function generate_and_execute_instrumented_binary() { local path_to_binary="${1}"; shift - local gcda_directory="${1}"; shift - # -fprofile-arcs Instruments $path_to_binary. During execution the binary - # records code coverage information. - # -ftest-coverage Produces a notes (.gcno) file that coverage utilities - # (e.g. gcov, lcov) can use to show a coverage report. - # -fprofile-dir Sets the directory where the profile data (gcda) appears. - # - # The profile data files need to be at a specific location where the C++ - # coverage scripts expects them to be ($COVERAGE_DIR/path/to/sources/). - g++ -fprofile-arcs -ftest-coverage \ - -fprofile-dir="$gcda_directory" \ + g++ -coverage \ "$@" -o "$path_to_binary" \ || fail "Couldn't produce the instrumented binary for $@ \ with path_to_binary $path_to_binary" @@ -274,6 +284,7 @@ EOF function test_cc_test_coverage_gcov() { + local -r gcov_location=$(which gcov) "$gcov_location" -version | grep "LLVM" && \ echo "gcov LLVM version not supported. Skipping test." && return # gcov -v | grep "gcov" outputs a line that looks like this: @@ -316,8 +327,16 @@ function test_cc_test_coverage_gcov() { fail "Number of lines in C++ gcov coverage output file is "\ "$nr_lines and different than 17" else - agcda=$(ls $COVERAGE_DIR_VAR/*a.gcda.gcov.json.gz) - tgcda=$(ls $COVERAGE_DIR_VAR/*t.gcda.gcov.json.gz) + # There may or may not be "gcda" in the extension. + local not_found=0 + ls $COVERAGE_DIR_VAR/*.gcda.gcov.json.gz > /dev/null 2>&1 || not_found=$? + if [[ $not_found -ne 0 ]]; then + agcda=$(ls $COVERAGE_DIR_VAR/*a.gcov.json.gz) + tgcda=$(ls $COVERAGE_DIR_VAR/*t.gcov.json.gz) + else + agcda=$(ls $COVERAGE_DIR_VAR/*a.gcda.gcov.json.gz) + tgcda=$(ls $COVERAGE_DIR_VAR/*t.gcda.gcov.json.gz) + fi output_file_json="output_file.json" zcat $agcda $tgcda > $output_file_json @@ -332,4 +351,4 @@ function test_cc_test_coverage_gcov() { fi } -run_suite "Testing tools/test/collect_cc_coverage.sh" \ No newline at end of file +run_suite "Testing tools/test/collect_cc_coverage.sh"