aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Kush Chakraborty <kush@google.com>2017-03-23 22:51:54 +0000
committerGravatar Yue Gan <yueg@google.com>2017-03-24 12:19:19 +0000
commit4443123db935fafd6f51f9c1f03bba1bc6538a22 (patch)
tree4a6b193856f1917a3195f2f189acc9e904d07180 /src/main
parentea862bac70646d519388955a71d6189a0f01459e (diff)
2nd attempt to split classpaths, and load test classes in a separate classloader. Currently this funcionality is hidden behind the "experimental_testrunner" flag.
Original description (from commit 786cfa2ed980e278c42ee474408844f7e3720385): Separate the classpaths of the TestRunner with the test target, and use a separate Classloader to load the test target's classes. This enables a clean separation of the classes of the TestRunner with the target under test. This is achieved with the following steps: 1. Start the test runner with only the bare bones classpaths to the Test Runner's classes which are used by the system ClassLoader. 2. Have all the classpaths required to load the test target's classes in a TEST_TARGET_CLASSPATH environment variable exported by the stub script. 3. Use a new classloader to load all the test target's classes using the paths in TEST_TARGET_CLASSPATH. This additionally enables the persistent test runner (currently experimental), to reload all the target's classes for every subsequent test run, so it can pick up any changes to the classes in between runs. The persistent test runner can be used by adding the argument --test_strategy=experimental_worker to the bazel test command (and having the tag "experimental_testrunner" in the java_test rule). Tested this against: 1. gerrit/gerrit-common:client_tests: Dismal avg. improvement of 580ms to 557ms (just 23ms) 2. intellij/intellij/base:unit_tests: Somewhat modest avg. improvement 1661ms to 913ms (748 ms) -- PiperOrigin-RevId: 151065529 MOS_MIGRATED_REVID=151065529
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java27
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt4
2 files changed, 23 insertions, 8 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
index 37ab7a0d6f..3a64342ead 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
@@ -34,7 +34,9 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.bazel.rules.BazelConfiguration;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.java.DeployArchiveBuilder;
import com.google.devtools.build.lib.rules.java.DeployArchiveBuilder.Compression;
import com.google.devtools.build.lib.rules.java.JavaCommon;
@@ -256,18 +258,27 @@ public class BazelJavaSemantics implements JavaSemantics {
arguments.add(Substitution.of("%needs_runfiles%",
ruleContext.getFragment(Jvm.class).getJavaExecutable().isAbsolute() ? "0" : "1"));
- NestedSetBuilder<Artifact> classpathBuilder = NestedSetBuilder.naiveLinkOrder();
TransitiveInfoCollection testSupport = getTestSupport(ruleContext);
- if (testSupport != null) {
- // Currently, this is only needed when experimental_testrunner=true, since in other cases the
- // testSupport classpath is already present in the javaCommon.getRuntimeClasspath().
- classpathBuilder.addTransitive(getRuntimeJarsForTargets(testSupport));
+ NestedSet<Artifact> classpath = javaCommon.getRuntimeClasspath();
+ NestedSet<Artifact> testTargetClasspath = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
+ if (TargetUtils.isTestRule(ruleContext.getRule())
+ && getMainClassFromRule(ruleContext).equals(EXPERIMENTAL_TEST_RUNNER_MAIN_CLASS)) {
+ // Experimental testRunner needs the testSupport to be present as it needs to start with
+ // *only* the testSupport classpaths.
+ Preconditions.checkNotNull(testSupport);
+ // Keep only the locations containing the classes to start the test runner itself within,
+ // classpath variable, and place all the paths required for the test run in
+ // testTargetClasspath, so that the classes for the test target may be loaded by a separate
+ // ClassLoader.
+ testTargetClasspath = classpath;
+ classpath = getRuntimeJarsForTargets(testSupport);
}
- classpathBuilder.addTransitive(javaCommon.getRuntimeClasspath());
-
arguments.add(
new ComputedClasspathSubstitution(
- "%classpath%", classpathBuilder.build(), workspacePrefix, isRunfilesEnabled));
+ "%classpath%", classpath, workspacePrefix, isRunfilesEnabled));
+ arguments.add(
+ new ComputedClasspathSubstitution(
+ "%test_target_classpath%", testTargetClasspath, workspacePrefix, isRunfilesEnabled));
JavaCompilationArtifacts javaArtifacts = javaCommon.getJavaCompilationArtifacts();
String path =
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
index cdc7ee4aa7..312976f586 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
@@ -228,6 +228,10 @@ else
CLASSPATH=%classpath%
fi
+# Export the classpaths which would be used to load the classes of the test target as an
+# environment variable.
+export TEST_TARGET_CLASSPATH=%test_target_classpath%
+
# If using Jacoco in offline instrumentation mode, the CLASSPATH contains instrumented files.
# We need to make the metadata jar with uninstrumented classes available for generating
# the lcov-compatible coverage report, and we don't want it on the classpath.