Skip to content

Commit 2770799

Browse files
fmeumcopybara-github
authored andcommitted
Collect coverage from cc_binary data deps of java_test
Before this commit, if a java_test executed a cc_binary from its data deps, coverage for this cc_binary would not be collected. This is fixed by adding the implicit `$collect_cc_coverage` attribute to BazelJavaTestRule, similar to how this is already done for BazelShTestRule. Fixes the Java part of bazelbuild#15098. Closes bazelbuild#15096. PiperOrigin-RevId: 438785232
1 parent 397f108 commit 2770799

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaTestRule.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
6262
attr(":lcov_merger", LABEL)
6363
.cfg(ExecutionTransitionFactory.create())
6464
.value(BaseRuleClasses.getCoverageOutputGeneratorLabel()))
65+
// Add the script as an attribute in order for java_test to output code coverage results for
66+
// code covered by CC binaries invocations.
67+
.add(
68+
attr("$collect_cc_coverage", LABEL)
69+
.cfg(ExecutionTransitionFactory.create())
70+
.singleArtifact()
71+
.value(env.getToolsLabel("//tools/test:collect_cc_coverage")))
6572
/* <!-- #BLAZE_RULE(java_test).ATTRIBUTE(test_class) -->
6673
The Java class to be loaded by the test runner.<br/>
6774
<p>

src/test/shell/bazel/bazel_coverage_java_test.sh

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,25 @@ EOF
8989
cat $(rlocation io_bazel/src/test/shell/bazel/testdata/jdk_http_archives) >> WORKSPACE
9090
}
9191

92+
# Returns 0 if gcov is not installed or if a version before 7.0 was found.
93+
# Returns 1 otherwise.
94+
function is_gcov_missing_or_wrong_version() {
95+
local -r gcov_location=$(which gcov)
96+
if [[ ! -x ${gcov_location:-/usr/bin/gcov} ]]; then
97+
echo "gcov not installed."
98+
return 0
99+
fi
100+
101+
"$gcov_location" -version | grep "LLVM" && \
102+
echo "gcov LLVM version not supported." && return 0
103+
# gcov -v | grep "gcov" outputs a line that looks like this:
104+
# gcov (Debian 7.3.0-5) 7.3.0
105+
local gcov_version="$(gcov -v | grep "gcov" | cut -d " " -f 4 | cut -d "." -f 1)"
106+
[ "$gcov_version" -lt 7 ] \
107+
&& echo "gcov versions before 7.0 is not supported." && return 0
108+
return 1
109+
}
110+
92111
# Asserts if the given expected coverage result is included in the given output
93112
# file.
94113
#
@@ -990,4 +1009,138 @@ BRH:5"
9901009
assert_coverage_result "$expected_result" "$coverage_file_path"
9911010
}
9921011

1012+
function test_java_test_coverage_cc_binary() {
1013+
if is_gcov_missing_or_wrong_version; then
1014+
echo "Skipping test." && return
1015+
fi
1016+
1017+
########### Setup source files and BUILD file ###########
1018+
cat <<EOF > BUILD
1019+
java_test(
1020+
name = "NumJava",
1021+
srcs = ["NumJava.java"],
1022+
data = ["//examples/cpp:num-world"],
1023+
main_class = "main.NumJava",
1024+
use_testrunner = False,
1025+
)
1026+
EOF
1027+
cat <<EOF > NumJava.java
1028+
package main;
1029+
1030+
public class NumJava {
1031+
public static void main(String[] args) throws java.io.IOException {
1032+
Runtime.getRuntime().exec("examples/cpp/num-world");
1033+
}
1034+
}
1035+
EOF
1036+
1037+
mkdir -p examples/cpp
1038+
1039+
cat <<EOF > examples/cpp/BUILD
1040+
package(default_visibility = ["//visibility:public"])
1041+
1042+
cc_binary(
1043+
name = "num-world",
1044+
srcs = ["num-world.cc"],
1045+
deps = [":num-lib"],
1046+
)
1047+
1048+
cc_library(
1049+
name = "num-lib",
1050+
srcs = ["num-lib.cc"],
1051+
hdrs = ["num-lib.h"]
1052+
)
1053+
EOF
1054+
1055+
cat <<EOF > examples/cpp/num-world.cc
1056+
#include "examples/cpp/num-lib.h"
1057+
1058+
using num::NumLib;
1059+
1060+
int main(int argc, char** argv) {
1061+
NumLib lib(30);
1062+
int value = 42;
1063+
if (argc > 1) {
1064+
value = 43;
1065+
}
1066+
lib.add_number(value);
1067+
return 0;
1068+
}
1069+
EOF
1070+
1071+
cat <<EOF > examples/cpp/num-lib.h
1072+
#ifndef EXAMPLES_CPP_NUM_LIB_H_
1073+
#define EXAMPLES_CPP_NUM_LIB_H_
1074+
1075+
namespace num {
1076+
1077+
class NumLib {
1078+
public:
1079+
explicit NumLib(int number);
1080+
1081+
int add_number(int value);
1082+
1083+
private:
1084+
int number_;
1085+
};
1086+
1087+
} // namespace num
1088+
1089+
#endif // EXAMPLES_CPP_NUM_LIB_H_
1090+
EOF
1091+
1092+
cat <<EOF > examples/cpp/num-lib.cc
1093+
#include "examples/cpp/num-lib.h"
1094+
1095+
namespace num {
1096+
1097+
NumLib::NumLib(int number) : number_(number) {
1098+
}
1099+
1100+
int NumLib::add_number(int value) {
1101+
return number_ + value;
1102+
}
1103+
1104+
} // namespace num
1105+
EOF
1106+
1107+
########### Run bazel coverage ###########
1108+
bazel coverage --test_output=all \
1109+
//:NumJava &>$TEST_log || fail "Coverage for //:NumJava failed"
1110+
1111+
########### Assert coverage results. ###########
1112+
local coverage_file_path="$( get_coverage_file_path_from_test_log )"
1113+
local expected_result_num_lib="SF:examples/cpp/num-lib.cc
1114+
FN:8,_ZN3num6NumLib10add_numberEi
1115+
FN:5,_ZN3num6NumLibC2Ei
1116+
FNDA:1,_ZN3num6NumLib10add_numberEi
1117+
FNDA:1,_ZN3num6NumLibC2Ei
1118+
FNF:2
1119+
FNH:2
1120+
DA:5,1
1121+
DA:6,1
1122+
DA:8,1
1123+
DA:9,1
1124+
LH:4
1125+
LF:4
1126+
end_of_record"
1127+
assert_coverage_result "$expected_result_num_lib" "$coverage_file_path"
1128+
local coverage_result_num_lib_header="SF:examples/cpp/num-world.cc
1129+
FN:5,main
1130+
FNDA:1,main
1131+
FNF:1
1132+
FNH:1
1133+
DA:5,1
1134+
DA:6,1
1135+
DA:7,1
1136+
DA:8,1
1137+
DA:9,0
1138+
DA:11,1
1139+
DA:12,1
1140+
LH:6
1141+
LF:7
1142+
end_of_record"
1143+
assert_coverage_result "$coverage_result_num_lib_header" "$coverage_file_path"
1144+
}
1145+
9931146
run_suite "test tests"

0 commit comments

Comments
 (0)