aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/junitrunner
diff options
context:
space:
mode:
authorGravatar Kush Chakraborty <kush@google.com>2017-03-08 15:30:59 +0000
committerGravatar Vladimir Moskva <vladmos@google.com>2017-03-09 10:27:29 +0000
commit4baedc7bf96bd06b36c4af241b7423d21b6ba424 (patch)
treec17272f6e4f49c539f708b0b79517b543622f76e /src/java_tools/junitrunner
parentcb8a5e25382cb67a80449ac1fb78ae9680650b92 (diff)
Create ExperimentalTestRunner which is just the same as BazelTestRunner, but a testbed of upcoming changes, without breaking existing test targets.
To use the alternate test runner a java test should add the tag "experimental_testrunner" and depend on "@bazel_tools//tools/jdk:ExperimentalTestRunner_deploy.jar" (instead of @bazel_tools//tools/jdk:TestRunner_deploy.jar) -- PiperOrigin-RevId: 149536298 MOS_MIGRATED_REVID=149536298
Diffstat (limited to 'src/java_tools/junitrunner')
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/BUILD40
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunner.java16
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunnerModule.java36
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/ExperimentalTestRunner.java191
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/ResultWriterFactory.java3
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/StderrStreamFactory.java2
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/StdoutStreamFactory.java2
7 files changed, 269 insertions, 21 deletions
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BUILD b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BUILD
index 1699cb882b..c5a8006794 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BUILD
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BUILD
@@ -7,9 +7,41 @@ DEFAULT_VISIBILITY = [
package(default_visibility = ["//src:__subpackages__"])
+filegroup(
+ name = "common_runner_java_files",
+ srcs = glob(
+ ["*.java"],
+ exclude =
+ [
+ "BazelTestRunner.java",
+ "ExperimentalTestRunner.java",
+ ],
+ ),
+)
+
java_library(
name = "test_runner",
- srcs = glob(["*.java"]),
+ srcs = [
+ "BazelTestRunner.java",
+ ":common_runner_java_files",
+ ],
+ data = ["//tools:test_sharding_compliant"],
+ deps = [
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/junit4",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/model",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/util",
+ "//third_party:junit4",
+ ],
+)
+
+java_library(
+ name = "experimental_test_runner",
+ srcs = [
+ "ExperimentalTestRunner.java",
+ ":common_runner_java_files",
+ ],
data = ["//tools:test_sharding_compliant"],
deps = [
"//src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal",
@@ -27,6 +59,12 @@ java_binary(
runtime_deps = [":test_runner"],
)
+java_binary(
+ name = "ExperimentalRunner",
+ main_class = "com.google.testing.junit.runner.ExperimentalTestRunner",
+ runtime_deps = [":experimental_test_runner"],
+)
+
filegroup(
name = "srcs",
testonly = 0, # All srcs should be not test only, overwrite package default.
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunner.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunner.java
index 74a6826f88..66d7d91a67 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunner.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunner.java
@@ -18,8 +18,6 @@ import com.google.testing.junit.runner.internal.StackTraces;
import com.google.testing.junit.runner.junit4.JUnit4InstanceModules.Config;
import com.google.testing.junit.runner.junit4.JUnit4InstanceModules.SuiteClass;
import com.google.testing.junit.runner.junit4.JUnit4Runner;
-import com.google.testing.junit.runner.model.AntXmlResultWriter;
-import com.google.testing.junit.runner.model.XmlResultWriter;
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -200,18 +198,4 @@ public class BazelTestRunner {
}
}
}
-
- static class BazelTestRunnerModule {
- static XmlResultWriter resultWriter(AntXmlResultWriter impl) {
- return impl;
- }
-
- static PrintStream stdoutStream() {
- return System.out;
- }
-
- static PrintStream stderrStream() {
- return System.err;
- }
- }
}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunnerModule.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunnerModule.java
new file mode 100644
index 0000000000..a3c1c6f796
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/BazelTestRunnerModule.java
@@ -0,0 +1,36 @@
+// Copyright 2017 The Bazel Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.testing.junit.runner;
+
+import com.google.testing.junit.runner.model.AntXmlResultWriter;
+import com.google.testing.junit.runner.model.XmlResultWriter;
+import java.io.PrintStream;
+
+/**
+ * Originally a Dagger module extracted out of {@link BazelTestRunner}.
+ */
+class BazelTestRunnerModule {
+ static XmlResultWriter resultWriter(AntXmlResultWriter impl) {
+ return impl;
+ }
+
+ static PrintStream stdoutStream() {
+ return System.out;
+ }
+
+ static PrintStream stderrStream() {
+ return System.err;
+ }
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/ExperimentalTestRunner.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/ExperimentalTestRunner.java
new file mode 100644
index 0000000000..f13915e8e9
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/ExperimentalTestRunner.java
@@ -0,0 +1,191 @@
+// Copyright 2017 The Bazel Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.testing.junit.runner;
+
+import com.google.testing.junit.runner.internal.StackTraces;
+import com.google.testing.junit.runner.junit4.JUnit4InstanceModules.Config;
+import com.google.testing.junit.runner.junit4.JUnit4InstanceModules.SuiteClass;
+import com.google.testing.junit.runner.junit4.JUnit4Runner;
+import java.io.PrintStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * For now the same as {@link BazelTestRunner} but intended to be a testbed to try out new features,
+ * without breeaking existing tests.
+ */
+public class ExperimentalTestRunner {
+ /**
+ * If no arguments are passed on the command line, use this System property to
+ * determine which test suite to run.
+ */
+ static final String TEST_SUITE_PROPERTY_NAME = "bazel.test_suite";
+
+ private ExperimentalTestRunner() {
+ // utility class; should not be instantiated
+ }
+
+ /**
+ * Takes as arguments the classes or packages to test.
+ *
+ * <p>To help just run one test or method in a suite, the test suite
+ * may be passed in via system properties (-Dbazel.test_suite).
+ * An empty args parameter means to run all tests in the suite.
+ * A non-empty args parameter means to run only the specified tests/methods.
+ *
+ * <p>Return codes:
+ * <ul>
+ * <li>Test runner failure, bad arguments, etc.: exit code of 2</li>
+ * <li>Normal test failure: exit code of 1</li>
+ * <li>All tests pass: exit code of 0</li>
+ * </ul>
+ */
+ public static void main(String[] args) {
+ PrintStream stderr = System.err;
+
+ String suiteClassName = System.getProperty(TEST_SUITE_PROPERTY_NAME);
+ System.out.println("WARNING: RUNNING EXPERIMENTAL TEST RUNNER");
+
+ if (args.length >= 1 && args[args.length - 1].equals("--persistent_test_runner")) {
+ System.err.println("Requested test strategy is currently unsupported.");
+ System.exit(1);
+ }
+
+ if (!checkTestSuiteProperty(suiteClassName)) {
+ System.exit(2);
+ }
+
+ int exitCode = runTestsInSuite(suiteClassName, args);
+
+ System.err.printf("%nExperimentalTestRunner exiting with a return value of %d%n", exitCode);
+ System.err.println("JVM shutdown hooks (if any) will run now.");
+ System.err.println("The JVM will exit once they complete.");
+ System.err.println();
+
+ printStackTracesIfJvmExitHangs(stderr);
+
+ DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date shutdownTime = new Date();
+ String formattedShutdownTime = format.format(shutdownTime);
+ System.err.printf("-- JVM shutdown starting at %s --%n%n", formattedShutdownTime);
+ System.exit(exitCode);
+ }
+
+ /**
+ * Ensures that the bazel.test_suite in argument is not {@code null} or print error and
+ * explanation.
+ *
+ * @param testSuiteProperty system property to check
+ */
+ private static boolean checkTestSuiteProperty(String testSuiteProperty) {
+ if (testSuiteProperty == null) {
+ System.err.printf(
+ "Error: The test suite Java system property %s is required but missing.%n",
+ TEST_SUITE_PROPERTY_NAME);
+ System.err.println();
+ System.err.println("This property is set automatically when running with Bazel like such:");
+ System.err.printf(" java -D%s=[test-suite-class] %s%n",
+ TEST_SUITE_PROPERTY_NAME, ExperimentalTestRunner.class.getName());
+ System.err.printf(" java -D%s=[test-suite-class] -jar [deploy-jar]%n",
+ TEST_SUITE_PROPERTY_NAME);
+ System.err.println("E.g.:");
+ System.err.printf(" java -D%s=org.example.testing.junit.runner.SmallTests %s%n",
+ TEST_SUITE_PROPERTY_NAME, ExperimentalTestRunner.class.getName());
+ System.err.printf(" java -D%s=org.example.testing.junit.runner.SmallTests "
+ + "-jar SmallTests_deploy.jar%n",
+ TEST_SUITE_PROPERTY_NAME);
+ return false;
+ }
+ return true;
+ }
+
+ private static int runTestsInSuite(String suiteClassName, String[] args) {
+ Class<?> suite = getTestClass(suiteClassName);
+
+ if (suite == null) {
+ // No class found corresponding to the system property passed in from Bazel
+ if (args.length == 0 && suiteClassName != null) {
+ System.err.printf("Class not found: [%s]%n", suiteClassName);
+ return 2;
+ }
+ }
+
+ // TODO(kush): Use a new classloader for the following instantiation.
+ JUnit4Runner runner =
+ JUnit4Bazel.builder()
+ .suiteClass(new SuiteClass(suite))
+ .config(new Config(args))
+ .build()
+ .runner();
+ return runner.run().wasSuccessful() ? 0 : 1;
+ }
+
+ private static Class<?> getTestClass(String name) {
+ if (name == null) {
+ return null;
+ }
+
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Prints out stack traces if the JVM does not exit quickly. This can help detect shutdown hooks
+ * that are preventing the JVM from exiting quickly.
+ *
+ * @param out Print stream to use
+ */
+ private static void printStackTracesIfJvmExitHangs(final PrintStream out) {
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ sleepUninterruptibly(5);
+ out.println("JVM still up after five seconds. Dumping stack traces for all threads.");
+ StackTraces.printAll(out);
+ }
+ }, "ExperimentalTestRunner: Print stack traces if JVM exit hangs");
+
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ /**
+ * Invokes SECONDS.{@link TimeUnit#sleep(long) sleep(sleepForSeconds)} uninterruptibly.
+ */
+ private static void sleepUninterruptibly(long sleepForSeconds) {
+ boolean interrupted = false;
+ try {
+ long end = System.nanoTime() + TimeUnit.SECONDS.toNanos(sleepForSeconds);
+ while (true) {
+ try {
+ // TimeUnit.sleep() treats negative timeouts just like zero.
+ TimeUnit.NANOSECONDS.sleep(end - System.nanoTime());
+ return;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/ResultWriterFactory.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/ResultWriterFactory.java
index ce8c70e790..34dcdf511c 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/ResultWriterFactory.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/ResultWriterFactory.java
@@ -32,8 +32,7 @@ public final class ResultWriterFactory implements Factory<XmlResultWriter> {
@Override
public XmlResultWriter get() {
- XmlResultWriter xmlResultWriter =
- BazelTestRunner.BazelTestRunnerModule.resultWriter(implSupplier.get());
+ XmlResultWriter xmlResultWriter = BazelTestRunnerModule.resultWriter(implSupplier.get());
assert xmlResultWriter != null;
return xmlResultWriter;
}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StderrStreamFactory.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StderrStreamFactory.java
index 22e45aeb84..be2303b793 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StderrStreamFactory.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StderrStreamFactory.java
@@ -25,7 +25,7 @@ public enum StderrStreamFactory implements Factory<PrintStream> {
@Override
public PrintStream get() {
- PrintStream printStream = BazelTestRunner.BazelTestRunnerModule.stderrStream();
+ PrintStream printStream = BazelTestRunnerModule.stderrStream();
assert printStream != null;
return printStream;
}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StdoutStreamFactory.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StdoutStreamFactory.java
index 6e0d6463f3..57517d5309 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StdoutStreamFactory.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/StdoutStreamFactory.java
@@ -25,7 +25,7 @@ public enum StdoutStreamFactory implements Factory<PrintStream> {
@Override
public PrintStream get() {
- PrintStream printStream = BazelTestRunner.BazelTestRunnerModule.stdoutStream();
+ PrintStream printStream = BazelTestRunnerModule.stdoutStream();
assert printStream != null;
return printStream;
}