Skip to content

Commit f38e293

Browse files
Googlercopybara-github
authored andcommitted
Filter coverage output to just the files in the source file manifest
Coverage output should be filtered to just the sources listed in the manifest because those are the sources of targets matched by --instrumentation_filter (excluding test targets unless --instrument_test_targets). Coverage output should be restricted to those files according to the documentation for those flags. This is a particular concern for C++ because C++ source files can include header files. That is, header files are source files of the target which directly includes them, but unlike most source files, code in header files may also be compiled by that target's consumers. Thus, CppCompile actions enable coverage instrumentation if either the target or any of the target's direct dependencies are matched by --instrumentation_filter. The resulting coverage output needs to be filtered to just the specific targets that are matched. However, C++ is not the only language which has that property. It's also possible for coverage implementations to generate overly-broad coverage data for other reasons, or as an oversight. In those cases, the semantics of --instrumentation_filter should still be enforced. This adds "jars" and "runtime_jars" to dependency attributes in the InstrumentationSpec for Java rules in order to preserve behavior for some of the tests. That test case doesn't seem like a usual way of structuring that dependency, if you have the source files checked in (as opposed to just the jarfile), it makes more sense to use the java_library target instead of using the jarfile output. But "jars" and "resource_jars" are in fact runtime dependencies, so listing them is at least technically correct. RELNOTES: Filter all (instead of just C++) source files for coverage output according to --instrumentation_filter and --instrument_test_targets. PiperOrigin-RevId: 344797828
1 parent fc2f2cf commit f38e293

6 files changed

Lines changed: 20 additions & 49 deletions

File tree

‎src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ public class JavaCommon {
6060
public static final InstrumentationSpec JAVA_COLLECTION_SPEC =
6161
new InstrumentationSpec(FileTypeSet.of(JavaSemantics.JAVA_SOURCE))
6262
.withSourceAttributes("srcs")
63-
.withDependencyAttributes("deps", "data", "resources", "exports", "runtime_deps");
63+
.withDependencyAttributes(
64+
"deps", "data", "resources", "resource_jars", "exports", "runtime_deps", "jars");
6465

6566
private ClasspathConfiguredFragment classpathFragment = new ClasspathConfiguredFragment();
6667
private JavaCompilationArtifacts javaArtifacts = JavaCompilationArtifacts.EMPTY;

‎tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/Constants.java‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
package com.google.devtools.coverageoutputgenerator;
1616

17-
import com.google.common.collect.ImmutableList;
18-
1917
/**
2018
* Stores markers used by the lcov tracefile and gcov intermediate format file. See <a
2119
* href="http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php">lcov documentation</a> and the flag
@@ -51,9 +49,4 @@ class Constants {
5149
static final String GCOV_BRANCH_NOTEXEC = "notexec";
5250
static final String GCOV_BRANCH_NOTTAKEN = "nottaken";
5351
static final String GCOV_BRANCH_TAKEN = "taken";
54-
// Please keep in sync with the extensions in CppFileTypes.
55-
static final ImmutableList<String> CC_EXTENSIONS =
56-
ImmutableList.of(
57-
".cc", ".cpp", ".cxx", ".c++", ".C", ".c", ".cu", ".cl", ".h", ".hh", ".hpp", ".ipp",
58-
".hxx", ".inc", ".inl", ".tlh", ".tli", ".H");
5952
}

‎tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/Coverage.java‎

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
package com.google.devtools.coverageoutputgenerator;
1616

17-
import static com.google.devtools.coverageoutputgenerator.Constants.CC_EXTENSIONS;
1817
import static java.util.Arrays.asList;
1918

2019
import com.google.common.base.Preconditions;
@@ -75,7 +74,7 @@ static Coverage create(List<SourceFileCoverage> sourceFilesCoverage) {
7574
* @param coverage The initial coverage.
7675
* @param sourcesToKeep The filenames of the sources to keep from the initial coverage.
7776
*/
78-
static Coverage getOnlyTheseCcSources(Coverage coverage, Set<String> sourcesToKeep) {
77+
static Coverage getOnlyTheseSources(Coverage coverage, Set<String> sourcesToKeep) {
7978
if (coverage == null || sourcesToKeep == null) {
8079
throw new IllegalArgumentException("Coverage and sourcesToKeep should not be null.");
8180
}
@@ -87,23 +86,13 @@ static Coverage getOnlyTheseCcSources(Coverage coverage, Set<String> sourcesToKe
8786
}
8887
Coverage finalCoverage = new Coverage();
8988
for (SourceFileCoverage source : coverage.getAllSourceFiles()) {
90-
if (!isCcSourceFile(source.sourceFileName())
91-
|| sourcesToKeep.contains(source.sourceFileName())) {
89+
if (sourcesToKeep.contains(source.sourceFileName())) {
9290
finalCoverage.add(source);
9391
}
9492
}
9593
return finalCoverage;
9694
}
9795

98-
private static boolean isCcSourceFile(String filename) {
99-
for (String ccExtension : CC_EXTENSIONS) {
100-
if (filename.endsWith(ccExtension)) {
101-
return true;
102-
}
103-
}
104-
return false;
105-
}
106-
10796
/**
10897
* Replaces the source file names in the current coverage with their mapping in the given map, if
10998
* it exists.

‎tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/Main.java‎

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
package com.google.devtools.coverageoutputgenerator;
1616

17-
import static com.google.devtools.coverageoutputgenerator.Constants.CC_EXTENSIONS;
1817
import static com.google.devtools.coverageoutputgenerator.Constants.GCOV_EXTENSION;
1918
import static com.google.devtools.coverageoutputgenerator.Constants.GCOV_JSON_EXTENSION;
2019
import static com.google.devtools.coverageoutputgenerator.Constants.PROFDATA_EXTENSION;
@@ -24,6 +23,7 @@
2423
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
2524

2625
import com.google.common.annotations.VisibleForTesting;
26+
import com.google.common.collect.ImmutableList;
2727
import com.google.common.collect.ImmutableMap;
2828
import com.google.common.collect.Lists;
2929
import java.io.BufferedReader;
@@ -36,7 +36,6 @@
3636
import java.nio.file.Path;
3737
import java.nio.file.Paths;
3838
import java.util.ArrayList;
39-
import java.util.Collections;
4039
import java.util.HashSet;
4140
import java.util.List;
4241
import java.util.Set;
@@ -75,7 +74,7 @@ static int runWithArgs(String... args) throws ExecutionException, InterruptedExc
7574
List<File> filesInCoverageDir =
7675
flags.coverageDir() != null
7776
? getCoverageFilesInDir(flags.coverageDir())
78-
: Collections.emptyList();
77+
: ImmutableList.of();
7978
Coverage coverage =
8079
Coverage.merge(
8180
parseFiles(
@@ -150,12 +149,9 @@ static int runWithArgs(String... args) throws ExecutionException, InterruptedExc
150149
}
151150

152151
if (flags.hasSourceFileManifest()) {
153-
// The source file manifest is only required for C++ code coverage.
154-
Set<String> ccSources = getCcSourcesFromSourceFileManifest(flags.sourceFileManifest());
155-
if (!ccSources.isEmpty()) {
156-
// Only filter out coverage if there were C++ sources found in the coverage manifest.
157-
coverage = Coverage.getOnlyTheseCcSources(coverage, ccSources);
158-
}
152+
coverage =
153+
Coverage.getOnlyTheseSources(
154+
coverage, getSourcesFromSourceFileManifest(flags.sourceFileManifest()));
159155
}
160156

161157
if (coverage.isEmpty()) {
@@ -198,13 +194,13 @@ static int runWithArgs(String... args) throws ExecutionException, InterruptedExc
198194
* <p>This method only returns the C++ source files, ignoring the other files as they are not
199195
* necessary when putting together the final coverage report.
200196
*/
201-
private static Set<String> getCcSourcesFromSourceFileManifest(String sourceFileManifest) {
197+
private static Set<String> getSourcesFromSourceFileManifest(String sourceFileManifest) {
202198
Set<String> sourceFiles = new HashSet<>();
203199
try (FileInputStream inputStream = new FileInputStream(new File(sourceFileManifest));
204200
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, UTF_8);
205201
BufferedReader reader = new BufferedReader(inputStreamReader)) {
206202
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
207-
if (!isMetadataFile(line) && isCcFile(line)) {
203+
if (!isMetadataFile(line)) {
208204
sourceFiles.add(line);
209205
}
210206
}
@@ -218,15 +214,6 @@ private static boolean isMetadataFile(String filename) {
218214
return filename.endsWith(".gcno") || filename.endsWith(".em");
219215
}
220216

221-
private static boolean isCcFile(String filename) {
222-
for (String ccExtension : CC_EXTENSIONS) {
223-
if (filename.endsWith(ccExtension)) {
224-
return true;
225-
}
226-
}
227-
return false;
228-
}
229-
230217
private static List<File> getGcovInfoFiles(List<File> filesInCoverageDir) {
231218
List<File> gcovFiles = getFilesWithExtension(filesInCoverageDir, GCOV_EXTENSION);
232219
if (gcovFiles.isEmpty()) {

‎tools/test/CoverageOutputGenerator/javatests/com/google/devtools/coverageoutputgenerator/CoverageTest.java‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,18 @@ public void testGetOnlyTheseSources() throws Exception {
191191

192192
assertThat(
193193
getSourceFileNames(
194-
Coverage.getOnlyTheseCcSources(coverage, sourcesToKeep).getAllSourceFiles()))
194+
Coverage.getOnlyTheseSources(coverage, sourcesToKeep).getAllSourceFiles()))
195195
.containsExactly("source/common/protobuf/utility.cc", "source/common/grpc/common.cc");
196196
}
197197

198198
@Test(expected = IllegalArgumentException.class)
199199
public void testGetOnlyTheseSourcesNullCoverage() {
200-
Coverage.getOnlyTheseCcSources(null, new HashSet<>());
200+
Coverage.getOnlyTheseSources(null, new HashSet<>());
201201
}
202202

203203
@Test(expected = IllegalArgumentException.class)
204204
public void testGetOnlyTheseSourcesNullSources() {
205-
Coverage.getOnlyTheseCcSources(new Coverage(), null);
205+
Coverage.getOnlyTheseSources(new Coverage(), null);
206206
}
207207

208208
@Test
@@ -213,7 +213,7 @@ public void testGetOnlyTheseSourcesEmptySources() throws Exception {
213213
coverage.add(new SourceFileCoverage("source/server/options.cc"));
214214
coverage.add(new SourceFileCoverage("source/server/manager.cc"));
215215

216-
assertThat(Coverage.getOnlyTheseCcSources(coverage, new HashSet<>()).getAllSourceFiles())
216+
assertThat(Coverage.getOnlyTheseSources(coverage, new HashSet<>()).getAllSourceFiles())
217217
.isEmpty();
218218
}
219219
}

‎tools/test/collect_coverage.sh‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,10 @@ fi
200200
#
201201
# --source_file_manifest The absolute path of the coverage source file
202202
# manifest. CoverageOutputGenerator uses this file to
203-
# keep only the C++ sources found in the manifest.
204-
# For other languages the sources in the manifest are
205-
# ignored.
203+
# keep only the sources found in the manifest (that is,
204+
# only the sources of targets matched by
205+
# --instrumentation_filter, excluding test targets
206+
# unless --instrument_test_targets).
206207

207208
if [[ "$IS_COVERAGE_SPAWN" == "1" ]]; then
208209
COVERAGE_DIR=$(resolve_links $COVERAGE_DIR)
@@ -231,4 +232,4 @@ fi
231232
# JAVA_RUNFILES is set to the runfiles of the test, which does not necessarily
232233
# contain a JVM (it does only if the test has a Java binary somewhere). So let
233234
# the LCOV merger discover where its own runfiles tree is.
234-
JAVA_RUNFILES= exec $LCOV_MERGER_CMD
235+
JAVA_RUNFILES= exec $LCOV_MERGER_CMD

0 commit comments

Comments
 (0)