Skip to content

Commit

Permalink
Collect coverage from cc_binary data deps of java_test
Browse files Browse the repository at this point in the history
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
  • Loading branch information
fmeum authored and copybara-github committed Apr 1, 2022
1 parent 397f108 commit 2770799
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
attr(":lcov_merger", LABEL)
.cfg(ExecutionTransitionFactory.create())
.value(BaseRuleClasses.getCoverageOutputGeneratorLabel()))
// Add the script as an attribute in order for java_test to output code coverage results for
// code covered by CC binaries invocations.
.add(
attr("$collect_cc_coverage", LABEL)
.cfg(ExecutionTransitionFactory.create())
.singleArtifact()
.value(env.getToolsLabel("//tools/test:collect_cc_coverage")))
/* <!-- #BLAZE_RULE(java_test).ATTRIBUTE(test_class) -->
The Java class to be loaded by the test runner.<br/>
<p>
Expand Down
153 changes: 153 additions & 0 deletions src/test/shell/bazel/bazel_coverage_java_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,25 @@ EOF
cat $(rlocation io_bazel/src/test/shell/bazel/testdata/jdk_http_archives) >> WORKSPACE
}

# Returns 0 if gcov is not installed or if a version before 7.0 was found.
# Returns 1 otherwise.
function is_gcov_missing_or_wrong_version() {
local -r gcov_location=$(which gcov)
if [[ ! -x ${gcov_location:-/usr/bin/gcov} ]]; then
echo "gcov not installed."
return 0
fi

"$gcov_location" -version | grep "LLVM" && \
echo "gcov LLVM version not supported." && return 0
# gcov -v | grep "gcov" outputs a line that looks like this:
# gcov (Debian 7.3.0-5) 7.3.0
local gcov_version="$(gcov -v | grep "gcov" | cut -d " " -f 4 | cut -d "." -f 1)"
[ "$gcov_version" -lt 7 ] \
&& echo "gcov versions before 7.0 is not supported." && return 0
return 1
}

# Asserts if the given expected coverage result is included in the given output
# file.
#
Expand Down Expand Up @@ -990,4 +1009,138 @@ BRH:5"
assert_coverage_result "$expected_result" "$coverage_file_path"
}

function test_java_test_coverage_cc_binary() {
if is_gcov_missing_or_wrong_version; then
echo "Skipping test." && return
fi

########### Setup source files and BUILD file ###########
cat <<EOF > BUILD
java_test(
name = "NumJava",
srcs = ["NumJava.java"],
data = ["//examples/cpp:num-world"],
main_class = "main.NumJava",
use_testrunner = False,
)
EOF
cat <<EOF > NumJava.java
package main;
public class NumJava {
public static void main(String[] args) throws java.io.IOException {
Runtime.getRuntime().exec("examples/cpp/num-world");
}
}
EOF

mkdir -p examples/cpp

cat <<EOF > examples/cpp/BUILD
package(default_visibility = ["//visibility:public"])
cc_binary(
name = "num-world",
srcs = ["num-world.cc"],
deps = [":num-lib"],
)
cc_library(
name = "num-lib",
srcs = ["num-lib.cc"],
hdrs = ["num-lib.h"]
)
EOF

cat <<EOF > examples/cpp/num-world.cc
#include "examples/cpp/num-lib.h"
using num::NumLib;
int main(int argc, char** argv) {
NumLib lib(30);
int value = 42;
if (argc > 1) {
value = 43;
}
lib.add_number(value);
return 0;
}
EOF

cat <<EOF > examples/cpp/num-lib.h
#ifndef EXAMPLES_CPP_NUM_LIB_H_
#define EXAMPLES_CPP_NUM_LIB_H_
namespace num {
class NumLib {
public:
explicit NumLib(int number);
int add_number(int value);
private:
int number_;
};
} // namespace num
#endif // EXAMPLES_CPP_NUM_LIB_H_
EOF

cat <<EOF > examples/cpp/num-lib.cc
#include "examples/cpp/num-lib.h"
namespace num {
NumLib::NumLib(int number) : number_(number) {
}
int NumLib::add_number(int value) {
return number_ + value;
}
} // namespace num
EOF

########### Run bazel coverage ###########
bazel coverage --test_output=all \
//:NumJava &>$TEST_log || fail "Coverage for //:NumJava failed"

########### Assert coverage results. ###########
local coverage_file_path="$( get_coverage_file_path_from_test_log )"
local expected_result_num_lib="SF:examples/cpp/num-lib.cc
FN:8,_ZN3num6NumLib10add_numberEi
FN:5,_ZN3num6NumLibC2Ei
FNDA:1,_ZN3num6NumLib10add_numberEi
FNDA:1,_ZN3num6NumLibC2Ei
FNF:2
FNH:2
DA:5,1
DA:6,1
DA:8,1
DA:9,1
LH:4
LF:4
end_of_record"
assert_coverage_result "$expected_result_num_lib" "$coverage_file_path"
local coverage_result_num_lib_header="SF:examples/cpp/num-world.cc
FN:5,main
FNDA:1,main
FNF:1
FNH:1
DA:5,1
DA:6,1
DA:7,1
DA:8,1
DA:9,0
DA:11,1
DA:12,1
LH:6
LF:7
end_of_record"
assert_coverage_result "$coverage_result_num_lib_header" "$coverage_file_path"
}

run_suite "test tests"

0 comments on commit 2770799

Please sign in to comment.