Skip to content

Commit

Permalink
Allow C/C++ coverage collection for external targets
Browse files Browse the repository at this point in the history
Removes hardcoded filters that result in no coverage being reported
for `cc_*` targets in external repositories even when matched by the
`--instrumentation_filter`.
  • Loading branch information
fmeum committed Sep 13, 2022
1 parent 19b299d commit 2b70dd5
Show file tree
Hide file tree
Showing 4 changed files with 332 additions and 2 deletions.
137 changes: 137 additions & 0 deletions src/test/shell/bazel/bazel_coverage_cc_test_gcc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -898,4 +898,141 @@ EOF
expect_log "WARNING: There was no coverage found."
}

function setup_external_cc_target() {
cat > WORKSPACE <<'EOF'
local_repository(
name = "other_repo",
path = "other_repo",
)
EOF

cat > BUILD <<'EOF'
cc_library(
name = "b",
srcs = ["b.cc"],
hdrs = ["b.h"],
visibility = ["//visibility:public"],
)
EOF

cat > b.h <<'EOF'
int b(bool what);
EOF

cat > b.cc <<'EOF'
int b(bool what) {
if (what) {
return 1;
} else {
return 2;
}
}
EOF

mkdir -p other_repo
touch other_repo/WORKSPACE

cat > other_repo/BUILD <<'EOF'
cc_library(
name = "a",
srcs = ["a.cc"],
hdrs = ["a.h"],
deps = ["@//:b"],
)
cc_test(
name = "t",
srcs = ["t.cc"],
linkstatic = True,
deps = [":a"],
)
EOF

cat > other_repo/a.h <<'EOF'
int a(bool what);
EOF

cat > other_repo/a.cc <<'EOF'
#include "a.h"
#include "b.h"
int a(bool what) {
if (what) {
return b(what);
} else {
return 1 + b(what);
}
}
EOF

cat > other_repo/t.cc <<'EOF'
#include <stdio.h>
#include "a.h"
int main(void) {
a(true);
}
EOF
}

function test_external_cc_target_can_collect_coverage() {
setup_external_cc_target

bazel coverage --test_output=all --instrumentation_filter=// @other_repo//:t \
&>"$TEST_log" || fail "Coverage for @other_repo//:t failed"

local coverage_file_path="$(get_coverage_file_path_from_test_log)"
local expected_result_a_cc='SF:external/other_repo/a.cc
FN:4,_Z1ab
FNDA:1,_Z1ab
FNF:1
FNH:1
DA:4,1
DA:5,1
DA:6,1
DA:8,0
LH:3
LF:4
end_of_record'
local expected_result_b_cc='SF:b.cc
FN:1,_Z1bb
FNDA:1,_Z1bb
FNF:1
FNH:1
DA:1,1
DA:2,1
DA:3,1
DA:5,0
LH:3
LF:4
end_of_record'

assert_coverage_result "$expected_result_a_cc" "$coverage_file_path"
assert_coverage_result "$expected_result_b_cc" "$coverage_file_path"
}

function test_external_cc_target_coverage_not_collected_by_default() {
setup_external_cc_target

bazel coverage --test_output=all @other_repo//:t \
&>"$TEST_log" || fail "Coverage for @other_repo//:t failed"

local coverage_file_path="$(get_coverage_file_path_from_test_log)"
local expected_result_b_cc='SF:b.cc
FN:1,_Z1bb
FNDA:1,_Z1bb
FNF:1
FNH:1
DA:1,1
DA:2,1
DA:3,1
DA:5,0
LH:3
LF:4
end_of_record'

assert_coverage_result "$expected_result_b_cc" "$coverage_file_path"
assert_not_contains "SF:external/other_repo/a.cc" "$coverage_file_path"
}

run_suite "test tests"
195 changes: 195 additions & 0 deletions src/test/shell/bazel/bazel_coverage_cc_test_llvm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,200 @@ end_of_record"
assert_equals "$expected_result" "$(cat $(get_coverage_file_path_from_test_log))"
}

function setup_external_cc_target() {
cat > WORKSPACE <<'EOF'
local_repository(
name = "other_repo",
path = "other_repo",
)
EOF

cat > BUILD <<'EOF'
cc_library(
name = "b",
srcs = ["b.cc"],
hdrs = ["b.h"],
visibility = ["//visibility:public"],
)
EOF

cat > b.h <<'EOF'
int b(bool what);
EOF

cat > b.cc <<'EOF'
int b(bool what) {
if (what) {
return 1;
} else {
return 2;
}
}
EOF

mkdir -p other_repo
touch other_repo/WORKSPACE

cat > other_repo/BUILD <<'EOF'
cc_library(
name = "a",
srcs = ["a.cc"],
hdrs = ["a.h"],
deps = ["@//:b"],
)
cc_test(
name = "t",
srcs = ["t.cc"],
linkstatic = True,
deps = [":a"],
)
EOF

cat > other_repo/a.h <<'EOF'
int a(bool what);
EOF

cat > other_repo/a.cc <<'EOF'
#include "a.h"
#include "b.h"
int a(bool what) {
if (what) {
return b(what);
} else {
return 1 + b(what);
}
}
EOF

cat > other_repo/t.cc <<'EOF'
#include <stdio.h>
#include "a.h"
int main(void) {
a(true);
}
EOF
}

function test_external_cc_target_can_collect_coverage() {
local -r clang_tool=$(which clang)
if [[ ! -x ${clang_tool:-/usr/bin/clang-9} ]]; then
echo "clang not installed. Skipping test."
return
fi

local -r llvm_cov=$(which llvm-cov)
if [[ ! -x ${llvm_cov:-/usr/bin/llvm-cov-9} ]]; then
echo "llvm-cov not installed. Skipping test."
return
fi

local -r llvm_profdata=$(which llvm-profdata)
if [[ ! -x ${llvm_profdata:-/usr/bin/llvm-profdata-9} ]]; then
echo "llvm-profdata not installed. Skipping test."
return
fi

setup_external_cc_target

BAZEL_USE_LLVM_NATIVE_COVERAGE=1 GCOV=$llvm_profdata CC=$clang_tool \
BAZEL_LLVM_COV=$llvm_cov bazel coverage --experimental_generate_llvm_lcov \
--combined_report=lcov --test_output=all \
@other_repo//:t --instrumentation_filter=// &>$TEST_log || fail "Coverage for @other_repo//:t failed"

local expected_result='SF:b.cc
FN:1,_Z1bb
FNDA:1,_Z1bb
FNF:1
FNH:1
BRDA:2,0,0,1
BRDA:2,0,1,0
BRF:2
BRH:1
DA:1,1
DA:2,1
DA:3,1
DA:4,1
DA:5,0
DA:6,0
DA:7,1
LH:5
LF:7
end_of_record
SF:external/other_repo/a.cc
FN:4,_Z1ab
FNDA:1,_Z1ab
FNF:1
FNH:1
BRDA:5,0,0,1
BRDA:5,0,1,0
BRF:2
BRH:1
DA:4,1
DA:5,1
DA:6,1
DA:7,1
DA:8,0
DA:9,0
DA:10,1
LH:5
LF:7
end_of_record'

assert_equals "$expected_result" "$(cat $(get_coverage_file_path_from_test_log))"
assert_equals "$expected_result" "$(cat bazel-out/_coverage/_coverage_report.dat)"
}

function test_external_cc_target_coverage_not_collected_by_default() {
local -r clang_tool=$(which clang)
if [[ ! -x ${clang_tool:-/usr/bin/clang-9} ]]; then
echo "clang not installed. Skipping test."
return
fi

local -r llvm_cov=$(which llvm-cov)
if [[ ! -x ${llvm_cov:-/usr/bin/llvm-cov-9} ]]; then
echo "llvm-cov not installed. Skipping test."
return
fi

local -r llvm_profdata=$(which llvm-profdata)
if [[ ! -x ${llvm_profdata:-/usr/bin/llvm-profdata-9} ]]; then
echo "llvm-profdata not installed. Skipping test."
return
fi

setup_external_cc_target

BAZEL_USE_LLVM_NATIVE_COVERAGE=1 GCOV=$llvm_profdata CC=$clang_tool \
BAZEL_LLVM_COV=$llvm_cov bazel coverage --experimental_generate_llvm_lcov \
--combined_report=lcov --test_output=all \
@other_repo//:t &>$TEST_log || fail "Coverage for @other_repo//:t failed"

local expected_result='SF:b.cc
FN:1,_Z1bb
FNDA:1,_Z1bb
FNF:1
FNH:1
BRDA:2,0,0,1
BRDA:2,0,1,0
BRF:2
BRH:1
DA:1,1
DA:2,1
DA:3,1
DA:4,1
DA:5,0
DA:6,0
DA:7,1
LH:5
LF:7
end_of_record'

assert_equals "$expected_result" "$(cat $(get_coverage_file_path_from_test_log))"
assert_equals "$expected_result" "$(cat bazel-out/_coverage/_coverage_report.dat)"
}

run_suite "test tests"
1 change: 0 additions & 1 deletion tools/test/collect_cc_coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ function llvm_coverage_lcov() {
done < "${COVERAGE_MANIFEST}"

"${LLVM_COV}" export -instr-profile "${output_file}.data" -format=lcov \
-ignore-filename-regex='.*external/.+' \
-ignore-filename-regex='/tmp/.+' \
${object_param} | sed 's#/proc/self/cwd/##' > "${output_file}"
}
Expand Down
1 change: 0 additions & 1 deletion tools/test/collect_coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ LCOV_MERGER_CMD="${LCOV_MERGER} --coverage_dir=${COVERAGE_DIR} \
--filter_sources=/usr/lib/.+ \
--filter_sources=/usr/include.+ \
--filter_sources=/Applications/.+ \
--filter_sources=.*external/.+ \
--source_file_manifest=${COVERAGE_MANIFEST}"

if [[ $COVERAGE_REPORTED_TO_ACTUAL_SOURCES_FILE ]]; then
Expand Down

0 comments on commit 2b70dd5

Please sign in to comment.