aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Damien Martin-Guillerez <dmarting@google.com>2016-01-13 09:39:16 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-01-13 13:19:15 +0000
commit0e396b827bca5ee507aadc875169e47d959a7136 (patch)
treee79d73a63c2148ca122af209f224ef1152e3ced8
parent45fdee15c5d276462f4cb86d402551f02ac8bb0b (diff)
Use our java test runner in Bazel
RELNOTES[NEW]: A new java test runner that support XML output and test filtering is supported. It can be used by specifying --nolegacy_bazel_java_test or by speicifying the test_class attribute on a java_test. -- MOS_MIGRATED_REVID=112028955
-rw-r--r--examples/java-native/src/test/java/com/example/myproject/BUILD10
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java34
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java162
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaTestRule.java46
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java17
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java6
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java2
-rw-r--r--src/test/shell/bazel/BUILD1
-rwxr-xr-xsrc/test/shell/bazel/bazel_example_test.sh7
-rwxr-xr-xsrc/test/shell/bazel/test-setup.sh1
-rwxr-xr-xsrc/test/shell/bazel/testenv.sh1
11 files changed, 260 insertions, 27 deletions
diff --git a/examples/java-native/src/test/java/com/example/myproject/BUILD b/examples/java-native/src/test/java/com/example/myproject/BUILD
index 9a91a8288b..b9d81a1ff8 100644
--- a/examples/java-native/src/test/java/com/example/myproject/BUILD
+++ b/examples/java-native/src/test/java/com/example/myproject/BUILD
@@ -17,6 +17,16 @@ java_test(
)
java_test(
+ name = "custom_with_test_class",
+ srcs = glob(["Test*.java"]),
+ test_class = "com.example.myproject.TestCustomGreeting",
+ deps = [
+ "//examples/java-native/src/main/java/com/example/myproject:custom-greeting",
+ "//third_party:junit4",
+ ],
+)
+
+java_test(
name = "fail",
srcs = ["Fail.java"],
deps = ["//third_party:junit4"],
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java
index 0dea311192..b065913bcb 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java
@@ -25,10 +25,13 @@ import static com.google.devtools.build.lib.syntax.Type.STRING;
import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.Constants;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.bazel.rules.cpp.BazelCppRuleClasses;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.PredicateWithMessage;
import com.google.devtools.build.lib.packages.Rule;
@@ -38,6 +41,7 @@ import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.RuleClass.PackageNameConstraint;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
+import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileTypeSet;
import java.util.Set;
@@ -50,6 +54,9 @@ public class BazelJavaRuleClasses {
public static final PredicateWithMessage<Rule> JAVA_PACKAGE_NAMES = new PackageNameConstraint(
PackageNameConstraint.ANY_SEGMENT, "java", "javatests");
+ protected static final String JUNIT_TESTRUNNER =
+ Constants.TOOLS_REPOSITORY + "//tools/jdk:TestRunner_deploy.jar";
+
public static final ImplicitOutputsFunction JAVA_BINARY_IMPLICIT_OUTPUTS =
fromFunctions(
JavaSemantics.JAVA_BINARY_CLASS_JAR,
@@ -268,6 +275,7 @@ public class BazelJavaRuleClasses {
* Base class for rule definitions producing Java binaries.
*/
public static final class BaseJavaBinaryRule implements RuleDefinition {
+
@Override
public RuleClass build(Builder builder, final RuleDefinitionEnvironment env) {
return builder
@@ -298,6 +306,23 @@ public class BazelJavaRuleClasses {
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("jvm_flags", STRING_LIST))
+ /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(use_testrunner) -->
+ Use the
+ <code>com.google.testing.junit.runner.GoogleTestRunner</code> class as the
+ main entry point for a Java program.
+ ${SYNOPSIS}
+
+ You can use this to override the default
+ behavior, which is to use <code>BazelTestRunner</code> for
+ <code>java_test</code> rules,
+ and not use it for <code>java_binary</code> rules. It is unlikely
+ you will want to do this. One use is for <code>AllTest</code>
+ rules that are invoked by another rule (to set up a database
+ before running the tests, for example). The <code>AllTest</code>
+ rule must be declared as a <code>java_binary</code>, but should
+ still use the test runner as its main entry point.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr("use_testrunner", BOOLEAN).value(false))
/* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(main_class) -->
Name of class with <code>main()</code> method to use as entry point.
${SYNOPSIS}
@@ -322,6 +347,15 @@ public class BazelJavaRuleClasses {
.add(attr("create_executable", BOOLEAN)
.nonconfigurable("internal")
.value(true))
+ .add(attr("$testsupport", LABEL).value(
+ new Attribute.ComputedDefault("use_testrunner") {
+ @Override
+ public Object getDefault(AttributeMap rule) {
+ return rule.get("use_testrunner", Type.BOOLEAN)
+ ? env.getLabel(JUNIT_TESTRUNNER)
+ : null;
+ }
+ }))
/* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(deploy_manifest_lines) -->
${SYNOPSIS}
A list of lines to add to the <code>META-INF/manifest.mf</code> file generated for the
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 182c2130f5..f55c0d939f 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
@@ -16,11 +16,14 @@ package com.google.devtools.build.lib.bazel.rules.java;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
@@ -38,6 +41,7 @@ import com.google.devtools.build.lib.rules.java.JavaCompilationHelper;
import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.rules.java.JavaHelper;
import com.google.devtools.build.lib.rules.java.JavaPrimaryClassProvider;
+import com.google.devtools.build.lib.rules.java.JavaRunfilesProvider;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
import com.google.devtools.build.lib.rules.java.JavaTargetAttributes;
import com.google.devtools.build.lib.rules.java.JavaUtil;
@@ -51,6 +55,7 @@ import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
/**
* Semantics for Bazel Java rules
@@ -80,14 +85,29 @@ public class BazelJavaSemantics implements JavaSemantics {
}
}
- private String getMainClassInternal(RuleContext ruleContext) {
- return ruleContext.getRule().isAttrDefined("main_class", Type.STRING)
+ private String getMainClassInternal(RuleContext ruleContext, JavaCommon javaCommon) {
+ String mainClass = ruleContext.getRule().isAttrDefined("main_class", Type.STRING)
? ruleContext.attributes().get("main_class", Type.STRING) : "";
+ boolean createExecutable = ruleContext.attributes().get("create_executable", Type.BOOLEAN);
+ boolean useTestrunner = ruleContext.attributes().get("use_testrunner", Type.BOOLEAN)
+ && !useLegacyJavaTest(ruleContext);
+
+ if (createExecutable) {
+ if (useTestrunner) {
+ mainClass = "com.google.testing.junit.runner.BazelTestRunner";
+ } else { /* java_binary or non-Junit java_test */
+ if (mainClass.isEmpty()) {
+ mainClass = javaCommon.determinePrimaryClass(javaCommon.getSrcsArtifacts());
+ }
+ }
+ }
+
+ return mainClass;
}
private void checkMainClass(RuleContext ruleContext, JavaCommon javaCommon) {
boolean createExecutable = ruleContext.attributes().get("create_executable", Type.BOOLEAN);
- String mainClass = getMainClassInternal(ruleContext);
+ String mainClass = getMainClassInternal(ruleContext, javaCommon);
if (!createExecutable && !mainClass.isEmpty()) {
ruleContext.ruleError("main class must not be specified when executable is not created");
@@ -95,8 +115,7 @@ public class BazelJavaSemantics implements JavaSemantics {
if (createExecutable && mainClass.isEmpty()) {
if (javaCommon.getSrcsArtifacts().isEmpty()) {
- ruleContext.ruleError(
- "need at least one of 'main_class', 'use_testrunner' or Java source files");
+ ruleContext.ruleError("need at least one of 'main_class' or Java source files");
}
mainClass = javaCommon.determinePrimaryClass(javaCommon.getSrcsArtifacts());
if (mainClass == null) {
@@ -111,7 +130,7 @@ public class BazelJavaSemantics implements JavaSemantics {
@Override
public String getMainClass(RuleContext ruleContext, JavaCommon javaCommon) {
checkMainClass(ruleContext, javaCommon);
- return getMainClassInternal(ruleContext);
+ return getMainClassInternal(ruleContext, javaCommon);
}
@Override
@@ -198,9 +217,30 @@ public class BazelJavaSemantics implements JavaSemantics {
}
}
+ private TransitiveInfoCollection getTestSupport(RuleContext ruleContext) {
+ if (!isJavaBinaryOrJavaTest(ruleContext)) {
+ return null;
+ }
+ if (useLegacyJavaTest(ruleContext)) {
+ return null;
+ }
+
+ boolean createExecutable = ruleContext.attributes().get("create_executable", Type.BOOLEAN);
+ if (createExecutable && ruleContext.attributes().get("use_testrunner", Type.BOOLEAN)) {
+ return Iterables.getOnlyElement(ruleContext.getPrerequisites("$testsupport", Mode.TARGET));
+ } else {
+ return null;
+ }
+ }
+
@Override
public void addRunfilesForBinary(RuleContext ruleContext, Artifact launcher,
Runfiles.Builder runfilesBuilder) {
+ TransitiveInfoCollection testSupport = getTestSupport(ruleContext);
+ if (testSupport != null) {
+ runfilesBuilder.addTarget(testSupport, JavaRunfilesProvider.TO_RUNFILES);
+ runfilesBuilder.addTarget(testSupport, RunfilesProvider.DEFAULT_RUNFILES);
+ }
}
@Override
@@ -210,6 +250,13 @@ public class BazelJavaSemantics implements JavaSemantics {
@Override
public void collectTargetsTreatedAsDeps(
RuleContext ruleContext, ImmutableList.Builder<TransitiveInfoCollection> builder) {
+ TransitiveInfoCollection testSupport = getTestSupport(ruleContext);
+ if (testSupport != null) {
+ // TODO(bazel-team): The testsupport is used as the test framework
+ // and really only needs to be on the runtime, not compile-time
+ // classpath.
+ builder.add(testSupport);
+ }
}
@Override
@@ -230,17 +277,87 @@ public class BazelJavaSemantics implements JavaSemantics {
NestedSetBuilder<Artifact> filesBuilder,
RuleConfiguredTargetBuilder ruleBuilder) {
if (isJavaBinaryOrJavaTest(ruleContext)) {
- boolean createExec = ruleContext.attributes().get("create_executable", Type.BOOLEAN);
- ruleBuilder.add(JavaPrimaryClassProvider.class,
- new JavaPrimaryClassProvider(createExec ? getMainClassInternal(ruleContext) : null));
+ ruleBuilder.add(
+ JavaPrimaryClassProvider.class,
+ new JavaPrimaryClassProvider(getPrimaryClass(ruleContext, javaCommon)));
+ }
+ }
+
+ // TODO(dmarting): simplify that logic when we remove the legacy Bazel java_test behavior.
+ private String getPrimaryClassLegacy(RuleContext ruleContext, JavaCommon javaCommon) {
+ boolean createExecutable = ruleContext.attributes().get("create_executable", Type.BOOLEAN);
+ if (!createExecutable) {
+ return null;
}
+ return getMainClassInternal(ruleContext, javaCommon);
}
+ private String getPrimaryClassNew(RuleContext ruleContext, JavaCommon javaCommon) {
+ boolean createExecutable = ruleContext.attributes().get("create_executable", Type.BOOLEAN);
+ Set<Artifact> sourceFiles = ImmutableSet.copyOf(javaCommon.getSrcsArtifacts());
+
+ if (!createExecutable) {
+ return null;
+ }
+
+ boolean useTestrunner = ruleContext.attributes().get("use_testrunner", Type.BOOLEAN);
+
+ String testClass = ruleContext.getRule().isAttrDefined("test_class", Type.STRING)
+ ? ruleContext.attributes().get("test_class", Type.STRING) : "";
+
+ if (useTestrunner) {
+ if (testClass.isEmpty()) {
+ testClass = javaCommon.determinePrimaryClass(sourceFiles);
+ if (testClass == null) {
+ ruleContext.ruleError("cannot determine junit.framework.Test class "
+ + "(Found no source file '" + ruleContext.getTarget().getName()
+ + ".java' and package name doesn't include 'java' or 'javatests'. "
+ + "You might want to rename the rule or add a 'test_class' "
+ + "attribute.)");
+ }
+ }
+ return testClass;
+ } else {
+ if (!testClass.isEmpty()) {
+ ruleContext.attributeError("test_class", "this attribute is only meaningful to "
+ + "BazelTestRunner, but you are not using it (use_testrunner = 0)");
+ }
+
+ return getMainClassInternal(ruleContext, javaCommon);
+ }
+ }
+
+ private String getPrimaryClass(RuleContext ruleContext, JavaCommon javaCommon) {
+ return useLegacyJavaTest(ruleContext) ? getPrimaryClassLegacy(ruleContext, javaCommon)
+ : getPrimaryClassNew(ruleContext, javaCommon);
+ }
@Override
public Iterable<String> getJvmFlags(
RuleContext ruleContext, JavaCommon javaCommon, List<String> userJvmFlags) {
- return userJvmFlags;
+ ImmutableList.Builder<String> jvmFlags = ImmutableList.builder();
+ jvmFlags.addAll(userJvmFlags);
+
+ if (!useLegacyJavaTest(ruleContext)) {
+ if (ruleContext.attributes().get("use_testrunner", Type.BOOLEAN)) {
+ String testClass = ruleContext.getRule().isAttrDefined("test_class", Type.STRING)
+ ? ruleContext.attributes().get("test_class", Type.STRING) : "";
+ if (testClass.isEmpty()) {
+ testClass = javaCommon.determinePrimaryClass(javaCommon.getSrcsArtifacts());
+ }
+
+ if (testClass == null) {
+ ruleContext.ruleError("cannot determine test class");
+ } else {
+ // Always run junit tests with -ea (enable assertion)
+ jvmFlags.add("-ea");
+ // "suite" is a misnomer.
+ jvmFlags.add("-Dbazel.test_suite=" + ShellEscaper.escapeString(testClass));
+ }
+ }
+ }
+
+ return jvmFlags.build();
}
@Override
@@ -309,22 +426,29 @@ public class BazelJavaSemantics implements JavaSemantics {
@Override
public List<String> getExtraArguments(RuleContext ruleContext, JavaCommon javaCommon) {
if (ruleContext.getRule().getRuleClass().equals("java_test")) {
- if (ruleContext.getConfiguration().getTestArguments().isEmpty()
- && !ruleContext.attributes().isAttributeValueExplicitlySpecified("args")) {
- ImmutableList.Builder<String> builder = ImmutableList.builder();
- for (Artifact artifact : javaCommon.getSrcsArtifacts()) {
- PathFragment path = artifact.getRootRelativePath();
- String className = JavaUtil.getJavaFullClassname(FileSystemUtils.removeExtension(path));
- if (className != null) {
- builder.add(className);
+ if (useLegacyJavaTest(ruleContext)) {
+ if (ruleContext.getConfiguration().getTestArguments().isEmpty()
+ && !ruleContext.attributes().isAttributeValueExplicitlySpecified("args")) {
+ ImmutableList.Builder<String> builder = ImmutableList.builder();
+ for (Artifact artifact : javaCommon.getSrcsArtifacts()) {
+ PathFragment path = artifact.getRootRelativePath();
+ String className = JavaUtil.getJavaFullClassname(FileSystemUtils.removeExtension(path));
+ if (className != null) {
+ builder.add(className);
+ }
}
+ return builder.build();
}
- return builder.build();
}
}
return ImmutableList.<String>of();
}
+ private boolean useLegacyJavaTest(RuleContext ruleContext) {
+ return !ruleContext.attributes().isAttributeValueExplicitlySpecified("test_class")
+ && ruleContext.getFragment(JavaConfiguration.class).useLegacyBazelJavaTest();
+ }
+
@Override
public String getJavaBuilderMainClass() {
return JAVABUILDER_CLASS_NAME;
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaTestRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaTestRule.java
index e9d44bebe8..c3c5b7558c 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaTestRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaTestRule.java
@@ -17,6 +17,7 @@ package com.google.devtools.build.lib.bazel.rules.java;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.TRISTATE;
+import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
import static com.google.devtools.build.lib.syntax.Type.STRING;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
@@ -50,9 +51,45 @@ public final class BazelJavaTestRule implements RuleDefinition {
return builder
.requiresConfigurationFragments(JavaConfiguration.class, Jvm.class)
.setImplicitOutputsFunction(BazelJavaRuleClasses.JAVA_BINARY_IMPLICIT_OUTPUTS)
- .override(attr("main_class", STRING).value(JUNIT4_RUNNER))
.override(attr("stamp", TRISTATE).value(TriState.NO))
+ .override(attr("use_testrunner", BOOLEAN).value(true))
.override(attr(":java_launcher", LABEL).value(JavaSemantics.JAVA_LAUNCHER))
+ // TODO(dmarting): remove once we drop the legacy bazel java_test behavior.
+ .override(attr("main_class", STRING).value(JUNIT4_RUNNER))
+ /* <!-- #BLAZE_RULE(java_test).ATTRIBUTE(test_class) -->
+ The Java class to be loaded by the test runner.<br/>
+ ${SYNOPSIS}
+ <p>
+ By default, if this argument is not defined then the legacy mode is used and the
+ test arguments are used instead. Set the <code>--nolegacy_bazel_java_test</code> flag
+ to not fallback on the first argument.
+ </p>
+ <p>
+ This attribute specifies the name of a Java class to be run by
+ this test. It is rare to need to set this. If this argument is omitted, the Java class
+ whose name corresponds to the <code>name</code> of this
+ <code>java_test</code> rule will be used.
+ </p>
+ <p>
+ For JUnit3, the test class needs to either be a subclass of
+ <code>junit.framework.TestCase</code> or it needs to have a public
+ static <code>suite()</code> method that returns a
+ <code>junit.framework.Test</code> (or a subclass of <code>Test</code>).
+ For JUnit4, the class needs to be annotated with
+ <code>org.junit.runner.RunWith</code>.
+ </p>
+ <p>
+ This attribute allows several <code>java_test</code> rules to
+ share the same <code>Test</code>
+ (<code>TestCase</code>, <code>TestSuite</code>, ...). Typically
+ additional information is passed to it
+ (e.g. via <code>jvm_flags=['-Dkey=value']</code>) so that its
+ behavior differs in each case, such as running a different
+ subset of the tests. This attribute also enables the use of
+ Java tests outside the <code>javatests</code> tree.
+ </p>
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr("test_class", STRING))
.build();
}
@@ -81,10 +118,9 @@ ${IMPLICIT_OUTPUTS}
${ATTRIBUTE_DEFINITION}
<p>
-See the section on <a href="#java_binary_args">java_binary()</a> arguments, with the <i>caveat</i>
-that there is no <code>main_class</code> argument. This rule also supports all
-<a href="common-definitions.html#common-attributes-tests">attributes common to all test rules
-(*_test)</a>.
+See the section on <a href="#java_binary_args">java_binary()</a> arguments. This rule also
+supports all <a href="common-definitions.html#common-attributes-tests">attributes common
+to all test rules (*_test)</a>.
</p>
<h4 id="java_test_examples">Examples</h4>
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
index 246253a406..315cf67797 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
@@ -142,12 +142,16 @@ public final class JavaConfiguration extends Fragment {
private final ImmutableList<Label> translationTargets;
private final String javaCpu;
private final JavaOptimizationMode javaOptimizationMode;
-
+
private final Label javaToolchain;
+ // TODO(dmarting): remove when we have rolled out the new behavior
+ private final boolean legacyBazelJavaTest;
+
JavaConfiguration(boolean generateJavaDeps,
List<String> defaultJvmFlags, JavaOptions javaOptions, Label javaToolchain, String javaCpu,
- ImmutableList<String> defaultJavaBuilderJvmOpts) throws InvalidConfigurationException {
+ ImmutableList<String> defaultJavaBuilderJvmOpts)
+ throws InvalidConfigurationException {
this.commandLineJavacFlags =
ImmutableList.copyOf(JavaHelper.tokenizeJavaOptions(javaOptions.javacOpts));
this.javaLauncherLabel = javaOptions.javaLauncher;
@@ -169,6 +173,7 @@ public final class JavaConfiguration extends Fragment {
this.javaCpu = javaCpu;
this.javaToolchain = javaToolchain;
this.javaOptimizationMode = javaOptions.javaOptimizationMode;
+ this.legacyBazelJavaTest = javaOptions.legacyBazelJavaTest;
ImmutableList.Builder<Label> translationsBuilder = ImmutableList.builder();
for (String s : javaOptions.translationTargets) {
@@ -336,4 +341,12 @@ public final class JavaConfiguration extends Fragment {
public JavaOptimizationMode getJavaOptimizationMode() {
return javaOptimizationMode;
}
+
+ /**
+ * Returns true if java_test in Bazel should behave in legacy mode that existed before we
+ * open-sourced our test runner.
+ */
+ public boolean useLegacyBazelJavaTest() {
+ return legacyBazelJavaTest;
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
index df524dc3f4..2a091cacc9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
@@ -389,6 +389,12 @@ public class JavaOptions extends FragmentOptions {
help = "Applies desired link-time optimizations to Java binaries and tests.")
public JavaOptimizationMode javaOptimizationMode;
+ @Option(name = "legacy_bazel_java_test",
+ defaultValue = "true",
+ category = "undocumented",
+ help = "Use the legacy mode of Bazel for java_test.")
+ public boolean legacyBazelJavaTest;
+
@Override
public FragmentOptions getHost(boolean fallback) {
JavaOptions host = (JavaOptions) getDefault();
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
index 9fbf932952..2d7a0ad293 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
@@ -88,7 +88,7 @@ public final class BazelAnalysisMock extends AnalysisMock {
"filegroup(name='extdir', srcs=glob(['jdk/jre/lib/ext/*']))",
// "dummy" is needed so that RedirectChaser stops here
"filegroup(name='java', srcs = ['jdk/jre/bin/java', 'dummy'])",
- "exports_files(['JavaBuilder_deploy.jar','SingleJar_deploy.jar',",
+ "exports_files(['JavaBuilder_deploy.jar','SingleJar_deploy.jar','TestRunner_deploy.jar',",
" 'JavaBuilderCanary_deploy.jar', 'ijar', 'GenClass_deploy.jar'])");
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD
index b6f2dba217..8d0be17ac0 100644
--- a/src/test/shell/bazel/BUILD
+++ b/src/test/shell/bazel/BUILD
@@ -52,6 +52,7 @@ filegroup(
"//src:bazel",
"//src/java_tools/buildjar:JavaBuilder_deploy.jar",
"//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass:GenClass_deploy.jar",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner:Runner_deploy.jar",
"//src/java_tools/singlejar:SingleJar_deploy.jar",
"//src/main/tools:namespace-sandbox",
"//src/main/tools:process-wrapper",
diff --git a/src/test/shell/bazel/bazel_example_test.sh b/src/test/shell/bazel/bazel_example_test.sh
index 1596431479..d20139b408 100755
--- a/src/test/shell/bazel/bazel_example_test.sh
+++ b/src/test/shell/bazel/bazel_example_test.sh
@@ -70,6 +70,13 @@ function test_java_test() {
assert_test_fails "${java_native_tests}:resource-fail"
}
+function test_java_test_with_junitrunner() {
+ # Test with junitrunner.
+ setup_javatest_support
+ local java_native_tests=//examples/java-native/src/test/java/com/example/myproject
+ assert_test_ok "${java_native_tests}:custom_with_test_class"
+}
+
function test_java_test_with_workspace_name() {
local java_pkg=examples/java-native/src/main/java/com/example/myproject
# Use named workspace and test if we can still execute hello-world
diff --git a/src/test/shell/bazel/test-setup.sh b/src/test/shell/bazel/test-setup.sh
index 4130740399..b9cc243ee7 100755
--- a/src/test/shell/bazel/test-setup.sh
+++ b/src/test/shell/bazel/test-setup.sh
@@ -370,6 +370,7 @@ function create_new_workspace() {
ln -s "${javabuilder_path}" tools/jdk/JavaBuilder_deploy.jar
ln -s "${singlejar_path}" tools/jdk/SingleJar_deploy.jar
ln -s "${genclass_path}" tools/jdk/GenClass_deploy.jar
+ ln -s "${junitrunner_path}" tools/jdk/TestRunner_deploy.jar
ln -s "${ijar_path}" tools/jdk/ijar
touch WORKSPACE
diff --git a/src/test/shell/bazel/testenv.sh b/src/test/shell/bazel/testenv.sh
index b2f76ae7aa..c03fc99fbc 100755
--- a/src/test/shell/bazel/testenv.sh
+++ b/src/test/shell/bazel/testenv.sh
@@ -42,6 +42,7 @@ javabuilder_path="${TEST_SRCDIR}/src/java_tools/buildjar/JavaBuilder_deploy.jar"
langtools_path="${TEST_SRCDIR}/third_party/java/jdk/langtools/javac.jar"
singlejar_path="${TEST_SRCDIR}/src/java_tools/singlejar/SingleJar_deploy.jar"
genclass_path="${TEST_SRCDIR}/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClass_deploy.jar"
+junitrunner_path="${TEST_SRCDIR}/src/java_tools/junitrunner/java/com/google/testing/junit/runner/Runner_deploy.jar"
ijar_path="${TEST_SRCDIR}/third_party/ijar/ijar"
# Sandbox tools