Skip to content

Commit b84fab1

Browse files
Bencodested-xie
authored andcommitted
Add test coverage support to android_local_test
Adding test coverage support to `android_local_test`. #15827 Closes #15840. RELNOTES: Adds coverage metric support to android_local_test PiperOrigin-RevId: 508549884 Change-Id: I6977efa51ca1c7a6df1f776fe1a326d07989a185
1 parent eeaee3d commit b84fab1

File tree

7 files changed

+338
-15
lines changed

7 files changed

+338
-15
lines changed

src/main/java/com/google/devtools/build/lib/bazel/rules/android/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ java_library(
2727
"//src/main/java/com/google/devtools/build/lib/analysis:actions/custom_command_line",
2828
"//src/main/java/com/google/devtools/build/lib/analysis:analysis_cluster",
2929
"//src/main/java/com/google/devtools/build/lib/analysis:blaze_directories",
30+
"//src/main/java/com/google/devtools/build/lib/analysis:config/execution_transition_factory",
3031
"//src/main/java/com/google/devtools/build/lib/analysis:config/toolchain_type_requirement",
3132
"//src/main/java/com/google/devtools/build/lib/analysis:config/transitions/composing_transition_factory",
3233
"//src/main/java/com/google/devtools/build/lib/analysis:rule_definition_environment",

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

+12-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.bazel.rules.android;
1515

16+
import com.google.common.base.Preconditions;
1617
import com.google.common.collect.ImmutableList;
1718
import com.google.common.collect.Iterables;
1819
import com.google.devtools.build.lib.actions.Artifact;
@@ -34,6 +35,9 @@
3435
/** An implementation for the "android_local_test" rule. */
3536
public class BazelAndroidLocalTest extends AndroidLocalTestBase {
3637

38+
private static final String JACOCO_COVERAGE_RUNNER_MAIN_CLASS =
39+
"com.google.testing.coverage.JacocoCoverageRunner";
40+
3741
public BazelAndroidLocalTest() {
3842
super(BazelAndroidSemantics.INSTANCE);
3943
}
@@ -76,9 +80,14 @@ protected String addCoverageSupport(
7680
JavaTargetAttributes.Builder attributesBuilder,
7781
String mainClass)
7882
throws RuleErrorException {
79-
// coverage does not yet work with android_local_test
80-
ruleContext.throwWithRuleError("android_local_test does not yet support coverage");
81-
return "";
83+
// This method can be called only for *_binary/*_test targets.
84+
Preconditions.checkNotNull(executable);
85+
86+
helper.addCoverageSupport();
87+
88+
// We do not add the instrumented jar to the runtime classpath, but provide it in the shell
89+
// script via an environment variable.
90+
return JACOCO_COVERAGE_RUNNER_MAIN_CLASS;
8291
}
8392

8493
@Override

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
2626
import com.google.devtools.build.lib.analysis.RuleDefinition;
2727
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
28+
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
2829
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaRuleClasses.BaseJavaBinaryRule;
2930
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
3031
import com.google.devtools.build.lib.packages.RuleClass;
@@ -82,7 +83,11 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment envi
8283
.removeAttribute("main_class")
8384
.removeAttribute("resources")
8485
.removeAttribute("use_testrunner")
85-
.removeAttribute(":java_launcher")
86+
.removeAttribute(":java_launcher") // Input files for test actions collecting code coverage
87+
.add(
88+
attr(":lcov_merger", LABEL)
89+
.cfg(ExecutionTransitionFactory.create())
90+
.value(BaseRuleClasses.getCoverageOutputGeneratorLabel()))
8691
.cfg(
8792
new ConfigFeatureFlagTransitionFactory(AndroidFeatureFlagSetProvider.FEATURE_FLAG_ATTR))
8893
.build();

src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java

+58-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
2121
import com.google.devtools.build.lib.analysis.Allowlist;
2222
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
23+
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
2324
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
2425
import com.google.devtools.build.lib.analysis.RequiredConfigFragmentsProvider;
2526
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
@@ -29,6 +30,7 @@
2930
import com.google.devtools.build.lib.analysis.Runfiles;
3031
import com.google.devtools.build.lib.analysis.RunfilesProvider;
3132
import com.google.devtools.build.lib.analysis.RunfilesSupport;
33+
import com.google.devtools.build.lib.analysis.SourceManifestAction;
3234
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
3335
import com.google.devtools.build.lib.analysis.actions.Substitution;
3436
import com.google.devtools.build.lib.analysis.actions.Template;
@@ -66,6 +68,7 @@
6668
import com.google.devtools.build.lib.rules.java.OneVersionCheckActionBuilder;
6769
import com.google.devtools.build.lib.rules.java.proto.GeneratedExtensionRegistryProvider;
6870
import com.google.devtools.build.lib.util.OS;
71+
import com.google.devtools.build.lib.util.Pair;
6972
import com.google.devtools.build.lib.vfs.PathFragment;
7073
import java.util.ArrayList;
7174
import java.util.List;
@@ -292,7 +295,7 @@ public ConfiguredTarget create(RuleContext ruleContext)
292295
originalMainClass,
293296
filesToBuildBuilder,
294297
javaExecutable,
295-
/* createCoverageMetadataJar= */ true);
298+
/* createCoverageMetadataJar= */ false);
296299

297300
Artifact oneVersionOutputArtifact = null;
298301
JavaConfiguration javaConfig = ruleContext.getFragment(JavaConfiguration.class);
@@ -364,6 +367,60 @@ public ConfiguredTarget create(RuleContext ruleContext)
364367

365368
JavaInfo.Builder javaInfoBuilder = JavaInfo.Builder.create();
366369

370+
NestedSetBuilder<Pair<String, String>> coverageEnvironment = NestedSetBuilder.stableOrder();
371+
NestedSetBuilder<Artifact> coverageSupportFiles = NestedSetBuilder.stableOrder();
372+
if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
373+
374+
// Create an artifact that contains the runfiles relative paths of the jars on the runtime
375+
// classpath. Using SourceManifestAction is the only reliable way to match the runfiles
376+
// creation code.
377+
Artifact runtimeClasspathArtifact =
378+
ruleContext.getUniqueDirectoryArtifact(
379+
"runtime_classpath_for_coverage",
380+
"runtime_classpath.txt",
381+
ruleContext.getBinOrGenfilesDirectory());
382+
ruleContext.registerAction(
383+
new SourceManifestAction(
384+
SourceManifestAction.ManifestType.SOURCES_ONLY,
385+
ruleContext.getActionOwner(),
386+
runtimeClasspathArtifact,
387+
new Runfiles.Builder(
388+
ruleContext.getWorkspaceName(),
389+
ruleContext.getConfiguration().legacyExternalRunfiles())
390+
// This matches the code below in collectDefaultRunfiles.
391+
.addTransitiveArtifactsWrappedInStableOrder(javaCommon.getRuntimeClasspath())
392+
.build(),
393+
null,
394+
true));
395+
filesToBuildBuilder.add(runtimeClasspathArtifact);
396+
397+
// Pass the artifact through an environment variable in the coverage environment so it
398+
// can be read by the coverage collection script.
399+
coverageEnvironment.add(
400+
new Pair<>(
401+
"JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE", runtimeClasspathArtifact.getExecPathString()));
402+
// Add the file to coverageSupportFiles so it ends up as an input for the test action
403+
// when coverage is enabled.
404+
coverageSupportFiles.add(runtimeClasspathArtifact);
405+
406+
// Make single jar reachable from the coverage environment because it needs to be executed
407+
// by the coverage collection script.
408+
FilesToRunProvider singleJar = JavaToolchainProvider.from(ruleContext).getSingleJar();
409+
coverageEnvironment.add(
410+
new Pair<>("SINGLE_JAR_TOOL", singleJar.getExecutable().getExecPathString()));
411+
coverageSupportFiles.addTransitive(singleJar.getFilesToRun());
412+
}
413+
414+
javaCommon.addTransitiveInfoProviders(
415+
builder,
416+
javaInfoBuilder,
417+
filesToBuild,
418+
classJar,
419+
coverageEnvironment.build(),
420+
coverageSupportFiles.build());
421+
javaCommon.addGenJarsProvider(
422+
builder, javaInfoBuilder, outputs.genClass(), outputs.genSource());
423+
367424
javaCommon.addTransitiveInfoProviders(builder, javaInfoBuilder, filesToBuild, classJar);
368425
javaCommon.addGenJarsProvider(
369426
builder, javaInfoBuilder, outputs.genClass(), outputs.genSource());

src/test/java/com/google/devtools/build/lib/bazel/rules/android/BazelAndroidLocalTestTest.java

-10
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,6 @@ public void testDisallowPrecompiledJars() throws Exception {
6969
" srcs = ['lib.jar'])");
7070
}
7171

72-
@Test
73-
public void testCoverageThrowsError() throws Exception {
74-
useConfiguration("--collect_code_coverage");
75-
checkError("java/test",
76-
"test",
77-
"android_local_test does not yet support coverage",
78-
"android_local_test(name = 'test',",
79-
" srcs = ['test.java'])");
80-
}
81-
8272
@Test
8373
public void testNoAndroidAllJarsPropertiesFileThrowsError() throws Exception {
8474
checkError("java/test",

src/test/shell/bazel/android/BUILD

+19
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,25 @@ android_sh_test(
4949
],
5050
)
5151

52+
android_sh_test(
53+
name = "android_local_test_integration_test",
54+
size = "large",
55+
srcs = ["android_local_test_integration_test.sh"],
56+
data = [
57+
":android_helper",
58+
# TODO(b/226204219): Remove this dep once Bazel properly loads d8
59+
# in create_android_sdk_rules()
60+
"//external:android/d8_jar_import",
61+
"//external:android_sdk_for_testing",
62+
"//src/test/shell/bazel:test-deps",
63+
],
64+
# See https://github.com/bazelbuild/bazel/issues/8235
65+
tags = [
66+
"no-remote",
67+
"no_windows",
68+
],
69+
)
70+
5271
android_sh_test(
5372
name = "aapt_integration_test",
5473
size = "large",

0 commit comments

Comments
 (0)