aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/junitrunner/javatests
diff options
context:
space:
mode:
authorGravatar Kush Chakraborty <kush@google.com>2017-02-10 16:46:12 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2017-02-10 18:19:16 +0000
commit6fdef7b5bd0c9cab1d768c7dda07a460aa4fe25a (patch)
tree2f213747dba73a2825402e6072b65ea51898c602 /src/java_tools/junitrunner/javatests
parentbcff52f6ce1ceb7b263cf3b3c508fa9610d1253f (diff)
Move the JUnit runner tests to the same location as the Internal Repo.
-- PiperOrigin-RevId: 147159416 MOS_MIGRATED_REVID=147159416
Diffstat (limited to 'src/java_tools/junitrunner/javatests')
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD51
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestListener.java120
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestRunner.java77
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/SignalHandlersTest.java75
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/CancellableRequestFactoryTest.java226
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestNameListenerTest.java176
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestXmlListenerTest.java288
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/MemoizingRequestTest.java73
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4BazelMock.java201
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4ConfigTest.java118
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4OptionsTest.java133
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4RunnerTest.java628
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4TestModelBuilderTest.java172
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleConfigFactory.java42
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleMockRunListenerFactory.java44
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleProvideStdoutStreamFactory.java44
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingEnvironmentFactory.java45
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingFiltersFactory.java62
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleTickerFactory.java43
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleXmlResultWriterFactory.java51
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestCaseNodeTest.java146
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java65
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestSuiteNodeTest.java86
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/XmlWriterTest.java232
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/HashBackedShardingFilterTest.java42
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/RoundRobinShardingFilterTest.java61
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingEnvironmentTest.java45
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingFiltersTest.java94
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD24
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/ExampleObject.java64
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/Fifo.java41
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/InternationalCharsTest.java27
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/JUnit4TestbridgeExercises.java36
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/StackTraceExercises.java53
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/SuiteMethodTakesForever.java41
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/XmlOutputExercises.java111
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/GoogleTestSecurityManagerTest.java160
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestIntegrationsExporterTest.java58
-rw-r--r--src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestPropertyExporterTest.java67
39 files changed, 4122 insertions, 0 deletions
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD
new file mode 100644
index 0000000000..0dd82ccb6c
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/BUILD
@@ -0,0 +1,51 @@
+DEFAULT_VISIBILITY = [
+ "//src/java_tools/junitrunner:__subpackages__",
+]
+
+licenses(["notice"]) # Apache 2.0
+
+# Libraries
+# =========================================================
+java_library(
+ name = "tests",
+ testonly = 1,
+ srcs = glob(
+ ["**/*.java"],
+ exclude = ["testbed/*.java"],
+ ),
+ deps = [
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner:test_runner",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal:junit4",
+ "//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/sharding/api",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/testing",
+ "//src/java_tools/junitrunner/java/com/google/testing/junit/runner/util",
+ "//src/test/java/com/google/devtools/build/lib:testutil",
+ "//third_party:dagger",
+ "//third_party:guava",
+ "//third_party:jsr305",
+ "//third_party:jsr330_inject",
+ "//third_party:junit4",
+ "//third_party:mockito",
+ "//third_party:truth",
+ ],
+)
+
+# Tests
+# =========================================================
+java_test(
+ name = "AllTests",
+ args = glob(["**/*Test.java"]),
+ main_class = "com.google.testing.junit.runner.TestRunner",
+ use_testrunner = 0,
+ runtime_deps = [":tests"],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+ visibility = ["//src:__pkg__"],
+)
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestListener.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestListener.java
new file mode 100644
index 0000000000..2573574094
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestListener.java
@@ -0,0 +1,120 @@
+// Copyright 2016 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 org.junit.internal.AssumptionViolatedException;
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+/**
+ * A straightforward listener that prints to stdout/stderr whenever a test changes its state (e.g.
+ * started, finished, failed).
+ */
+class TestListener extends RunListener {
+ /**
+ * Called before any tests have been run. Prints to stdout the number of test cases found.
+ *
+ * @param description describes the tests to be run
+ */
+ @Override
+ public void testRunStarted(Description description) throws Exception {
+ System.out.println("Found " + formatTestCaseCount(description.testCount()) + ".");
+ }
+
+ /**
+ * Called when all tests have finished. Prints to stdout if the tests were successful or not. If
+ * not, it also prints the number of failed test cases. Finally, it prints the number of
+ * ignored test cases.
+ *
+ * @param result the summary of the test run, including all the tests that failed
+ */
+ @Override
+ public void testRunFinished(Result result) throws Exception {
+ if (result.wasSuccessful()) {
+ System.out.println("Successfully finished running "
+ + formatTestCaseCount(result.getRunCount()) + " in " + result.getRunTime() + " ms.");
+ } else {
+ System.out.println("Finished running " + formatTestCaseCount(result.getRunCount())
+ + " in " + result.getRunTime() + " ms.");
+ int failureCount = result.getFailureCount();
+ if (failureCount == 1) {
+ System.out.println("There was 1 failed test.");
+ } else {
+ System.out.println("There were " + failureCount + " failed tests.");
+ }
+ }
+ int ignoredCount = result.getIgnoreCount();
+ if (ignoredCount == 1) {
+ System.out.println(result.getIgnoreCount() + " test case was ignored.");
+ } else if (ignoredCount > 1) {
+ System.out.println(result.getIgnoreCount() + " test cases were ignored.");
+ }
+ }
+
+ /**
+ * Called when an atomic test is about to be started. Prints to stdout the name of the test that
+ * started with the corresponding information.
+ *
+ * @param description the description of the test that is about to be run
+ * (generally a class and method name)
+ */
+ @Override
+ public void testStarted(Description description) throws Exception {
+ System.out.println("Test case started: " + description.getDisplayName());
+ }
+
+ /**
+ * Called when an atomic test fails. Prints to stderr the name of the test that failed
+ * (including its class) and the reason why, including the stack trace.
+ *
+ * @param failure describes the test that failed and the exception that was thrown
+ */
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ System.err.println("Failure in " + failure.getTestHeader() + ": " + failure.getMessage()
+ + "\n" + failure.getTrace());
+ }
+
+ /**
+ * Called when an atomic test flags that it assumes a condition that is false. Prints to stderr
+ * that a test case assumed false condition, including the corresponding message containing
+ * the context.
+ *
+ * @param failure describes the test that failed and the
+ * {@link AssumptionViolatedException} that was thrown
+ */
+ @Override
+ public void testAssumptionFailure(Failure failure) {
+ System.err.println("Test case assumed false condition: " + failure.getMessage());
+ }
+
+ /**
+ * Called when a test will not be run, generally because a test method is annotated with
+ * Ignore. Prints to stderr that a test case was ignored, alongside with the test name.
+ **/
+ @Override
+ public void testIgnored(Description description) throws java.lang.Exception {
+ System.err.println("Test case " + description.getMethodName() + " ignored.");
+ }
+
+ private static String formatTestCaseCount(int count) {
+ if (count == 1) {
+ return "1 test case";
+ }
+ return count + " test cases";
+ }
+ }
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestRunner.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestRunner.java
new file mode 100644
index 0000000000..35d361a35a
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/TestRunner.java
@@ -0,0 +1,77 @@
+// Copyright 2016 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.util.GoogleTestSecurityManager;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+
+/**
+ * A straightforward JUnit test runner that runs the test in the specified class using
+ * {@link JUnitCore}.
+ */
+public class TestRunner {
+ private static final String PACKAGE = TestRunner.class.getPackage().getName();
+
+ private TestRunner() {}
+
+ public static void main(String[] args) throws ClassNotFoundException {
+ if (args.length == 0) {
+ throw new IllegalArgumentException(
+ "Must specify at least one argument (source files of the tests to run)!");
+ }
+
+ JUnitCore junitCore = new JUnitCore();
+ junitCore.addListener(new TestListener());
+ SecurityManager previousSecurityManager = setGoogleTestSecurityManager();
+ Request request = createRequest(args);
+ Result result = junitCore.run(request);
+ restorePreviousSecurityManager(previousSecurityManager);
+
+ System.exit(result.wasSuccessful() ? 0 : 1);
+ }
+
+ private static Request createRequest(String[] filepaths) throws ClassNotFoundException {
+ List<Class<?>> classes = new ArrayList<>(filepaths.length);
+ for (String path : filepaths) {
+ classes.add(getClass(path));
+ }
+ return Request.classes(classes.toArray(new Class<?>[0]));
+ }
+
+ private static Class<?> getClass(String filepath) throws ClassNotFoundException {
+ String className = filepath.replace('/', '.');
+ if (filepath.endsWith(".java")) {
+ className = className.substring(0, className.length() - 5);
+ }
+ return Class.forName(PACKAGE + "." + className);
+ }
+
+ // Sets a new GoogleTestSecurityManager as security manager and returns the previous one.
+ private static SecurityManager setGoogleTestSecurityManager() {
+ SecurityManager previousSecurityManager = System.getSecurityManager();
+ GoogleTestSecurityManager newSecurityManager = new GoogleTestSecurityManager();
+ System.setSecurityManager(newSecurityManager);
+ return previousSecurityManager;
+ }
+
+ private static void restorePreviousSecurityManager(SecurityManager previousSecurityManager) {
+ GoogleTestSecurityManager.uninstallIfInstalled();
+ System.setSecurityManager(previousSecurityManager);
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/SignalHandlersTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/SignalHandlersTest.java
new file mode 100644
index 0000000000..038b427759
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/SignalHandlersTest.java
@@ -0,0 +1,75 @@
+// Copyright 2010 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.internal;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
+
+/**
+ * Tests for SignalHandlers.
+ */
+@RunWith(JUnit4.class)
+public class SignalHandlersTest {
+
+ private static final Signal TERM_SIGNAL = new Signal("TERM");
+
+ private final FakeSignalInstaller fakeSignalInstaller = new FakeSignalInstaller();
+ private final SignalHandlers signalHandlers = new SignalHandlers(fakeSignalInstaller);
+
+ static class FakeSignalInstaller implements SignalHandlers.HandlerInstaller {
+ private SignalHandler currentHandler = null;
+
+ @Override
+ public SignalHandler install(Signal signal, SignalHandler handler) {
+ SignalHandler previousHandler = currentHandler;
+ assertEquals("This fake only supports the TERM signal", TERM_SIGNAL, signal);
+ currentHandler = handler;
+ return previousHandler;
+ }
+
+ public void sendSignal() {
+ currentHandler.handle(TERM_SIGNAL);
+ }
+ }
+
+ @Test
+ public void testHandlersCanBeChained() {
+ SignalHandler handler1 = Mockito.mock(SignalHandler.class);
+ SignalHandler handler2 = Mockito.mock(SignalHandler.class);
+
+ signalHandlers.installHandler(TERM_SIGNAL, handler1);
+ signalHandlers.installHandler(TERM_SIGNAL, handler2);
+ fakeSignalInstaller.sendSignal();
+
+ Mockito.verify(handler1).handle(Mockito.eq(TERM_SIGNAL));
+ Mockito.verify(handler2).handle(Mockito.eq(TERM_SIGNAL));
+ }
+
+ @Test
+ public void testOneHandlerCanHandleSignal() {
+ SignalHandler handler = Mockito.mock(SignalHandler.class);
+
+ signalHandlers.installHandler(TERM_SIGNAL, handler);
+ fakeSignalInstaller.sendSignal();
+
+ Mockito.verify(handler).handle(Mockito.eq(TERM_SIGNAL));
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/CancellableRequestFactoryTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/CancellableRequestFactoryTest.java
new file mode 100644
index 0000000000..f89c7ab277
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/CancellableRequestFactoryTest.java
@@ -0,0 +1,226 @@
+// Copyright 2012 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.internal.junit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.Test;
+import org.junit.internal.AssumptionViolatedException;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runner.notification.StoppedByUserException;
+import org.junit.runners.JUnit4;
+import org.junit.runners.Suite;
+import org.junit.runners.model.InitializationError;
+
+/**
+ * Tests for {@link CancellableRequestFactory}.
+ */
+@RunWith(JUnit4.class)
+public class CancellableRequestFactoryTest {
+
+ private final CancellableRequestFactory cancellableRequestFactory =
+ new CancellableRequestFactory();
+
+ @Test
+ public void testCancelRunAfterStarting() throws Exception {
+ final CountDownLatch testStartLatch = new CountDownLatch(1);
+ final CountDownLatch testContinueLatch = new CountDownLatch(1);
+ final AtomicBoolean secondTestRan = new AtomicBoolean(false);
+
+ // Simulates a test that hangs
+ FakeRunner blockingRunner = new FakeRunner("blocks", new Runnable() {
+ @Override
+ public void run() {
+ testStartLatch.countDown();
+ try {
+ testContinueLatch.await(1, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("Timed out waiting for signal to continue test", e);
+ }
+ }
+ });
+
+ // A runner that should never run its test
+ FakeRunner secondRunner = new FakeRunner("shouldNotRun", new Runnable() {
+ @Override
+ public void run() {
+ secondTestRan.set(true);
+ }
+ });
+
+ RunnerSuite fakeSuite = new RunnerSuite(blockingRunner, secondRunner);
+ final Request request = cancellableRequestFactory.createRequest(Request.runner(fakeSuite));
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Result> future = executor.submit(new Callable<Result>() {
+ @Override
+ public Result call() throws Exception {
+ JUnitCore core = new JUnitCore();
+ return core.run(request);
+ }
+ });
+
+ // Simulate cancel being called in the middle of the test
+ testStartLatch.await(1, TimeUnit.SECONDS);
+ cancellableRequestFactory.cancelRun();
+ testContinueLatch.countDown();
+
+ try {
+ future.get(10, TimeUnit.SECONDS);
+ fail("exception expected");
+ } catch (ExecutionException e) {
+ Throwable runnerException = e.getCause();
+ assertTrue(runnerException instanceof RuntimeException);
+ assertEquals("Test run interrupted", runnerException.getMessage());
+ assertTrue(runnerException.getCause() instanceof StoppedByUserException);
+ }
+
+ executor.shutdownNow();
+ }
+
+ @Test
+ public void testCancelRunBeforeStarting() throws Exception {
+ final AtomicBoolean testRan = new AtomicBoolean(false);
+
+ // A runner that should never run its test
+ FakeRunner runner = new FakeRunner("shouldNotRun", new Runnable() {
+ @Override
+ public void run() {
+ testRan.set(true);
+ }
+ });
+
+ Request request = cancellableRequestFactory.createRequest(Request.runner(runner));
+ cancellableRequestFactory.cancelRun();
+ JUnitCore core = new JUnitCore();
+
+ try {
+ core.run(request);
+ fail("exception expected");
+ } catch (RuntimeException e) {
+ assertEquals("Test run interrupted", e.getMessage());
+ assertTrue(e.getCause() instanceof StoppedByUserException);
+ }
+
+ assertFalse(testRan.get());
+ }
+
+ @Test
+ public void testNormalRun() {
+ final AtomicBoolean testRan = new AtomicBoolean(false);
+
+ // A runner that should run its test
+ FakeRunner runner = new FakeRunner("shouldRun", new Runnable() {
+ @Override
+ public void run() {
+ testRan.set(true);
+ }
+ });
+
+ Request request = cancellableRequestFactory.createRequest(Request.runner(runner));
+ JUnitCore core = new JUnitCore();
+ Result result = core.run(request);
+
+ assertTrue(testRan.get());
+ assertEquals(1, result.getRunCount());
+ assertEquals(0, result.getFailureCount());
+ }
+
+ @Test
+ public void testFailingRun() {
+ final AtomicBoolean testRan = new AtomicBoolean(false);
+ final RuntimeException expectedFailure = new RuntimeException();
+
+ // A runner that should run its test
+ FakeRunner runner = new FakeRunner("shouldRun", new Runnable() {
+ @Override
+ public void run() {
+ testRan.set(true);
+ throw expectedFailure;
+ }
+ });
+
+ Request request = cancellableRequestFactory.createRequest(Request.runner(runner));
+ JUnitCore core = new JUnitCore();
+ Result result = core.run(request);
+
+ assertTrue(testRan.get());
+ assertEquals(1, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertSame(expectedFailure, result.getFailures().get(0).getException());
+ }
+
+
+ private static class FakeRunner extends Runner {
+ private final Description testDescription;
+ private final Runnable test;
+
+ public FakeRunner(String testName, Runnable test) {
+ this.test = test;
+ testDescription = Description.createTestDescription(FakeRunner.class, testName);
+ }
+
+ @Override
+ public Description getDescription() {
+ return testDescription;
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ notifier.fireTestStarted(testDescription);
+
+ try {
+ test.run();
+ } catch (AssumptionViolatedException e) {
+ notifier.fireTestAssumptionFailed(new Failure(testDescription, e));
+ } catch (Throwable e) {
+ notifier.fireTestFailure(new Failure(testDescription, e));
+ } finally {
+ notifier.fireTestFinished(testDescription);
+ }
+ }
+ }
+
+ public static class FakeSuite {
+ }
+
+ public static class RunnerSuite extends Suite {
+
+ public RunnerSuite(Runner... runners) throws InitializationError {
+ super(FakeSuite.class, Arrays.asList(runners));
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestNameListenerTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestNameListenerTest.java
new file mode 100644
index 0000000000..a63788779b
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestNameListenerTest.java
@@ -0,0 +1,176 @@
+// Copyright 2011 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.internal.junit4;
+
+import static com.google.common.base.Throwables.throwIfUnchecked;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import com.google.testing.junit.runner.util.TestNameProvider;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JUnit4TestNameListener}.
+ */
+@RunWith(JUnit4.class)
+public class JUnit4TestNameListenerTest {
+ private JUnit4TestNameListener testNameListener;
+ private TestNameProvider testNameProviderForTesting;
+ @Rule public TestName name = new TestName();
+
+ @Before
+ public void setCurrentRunningTest() {
+ SettableCurrentRunningTest currentRunningTest = new SettableCurrentRunningTest() {
+ @Override
+ public void setGlobalTestNameProvider(TestNameProvider provider) {
+ testNameProviderForTesting = provider;
+ }
+ };
+
+ testNameListener = new JUnit4TestNameListener(currentRunningTest);
+ }
+
+ @Test
+ public void testJUnit4Listener_normalUsage() throws Exception {
+ assertNull(testNameProviderForTesting);
+
+ Description description = Description.createSuiteDescription(FakeTest.class);
+ testNameListener.testRunStarted(description);
+ assertNull(testNameProviderForTesting.get());
+
+ description = Description.createTestDescription(FakeTest.class, "methodName");
+ testNameListener.testStarted(description);
+ assertEquals(description, testNameProviderForTesting.get());
+ testNameListener.testFinished(description);
+ assertNull(testNameProviderForTesting.get());
+
+ description = Description.createTestDescription(FakeTest.class, "anotherMethodName");
+ testNameListener.testStarted(description);
+ assertEquals(description, testNameProviderForTesting.get());
+ testNameListener.testFinished(description);
+ assertNull(testNameProviderForTesting.get());
+
+ testNameListener.testRunFinished(null);
+ assertNull(testNameProviderForTesting.get());
+ }
+
+ @Test
+ public void testJUnit4Listener_hasExpectedDisplayName() throws Exception {
+ Description description = Description.createSuiteDescription(FakeTest.class);
+ testNameListener.testRunStarted(description);
+
+ description = Description.createTestDescription(this.getClass(), name.getMethodName());
+ testNameListener.testStarted(description);
+ assertEquals("testJUnit4Listener_hasExpectedDisplayName("
+ + JUnit4TestNameListenerTest.class.getCanonicalName() + ")",
+ testNameProviderForTesting.get().getDisplayName());
+ }
+
+ @Test
+ public void testJUnit4Listener_multipleThreads() throws Exception {
+ ExecutorService executorService = Executors.newSingleThreadExecutor();
+ Description description1 =
+ Description.createTestDescription(FakeTest.class, "methodName");
+ final Description description2 =
+ Description.createTestDescription(FakeTest.class, "anotherMethodName");
+
+ testNameListener.testRunStarted(Description.createSuiteDescription(FakeTest.class));
+ assertNull(testNameProviderForTesting.get());
+ testNameListener.testStarted(description1);
+ assertEquals(description1, testNameProviderForTesting.get());
+
+ Future<?> startSecondTestFuture =
+ executorService.submit(
+ new Runnable() {
+ @Override
+ public void run() {
+ assertNull(testNameProviderForTesting.get());
+ try {
+ testNameListener.testStarted(description2);
+ } catch (Exception e) {
+ throwIfUnchecked(e);
+ throw new RuntimeException(e);
+ }
+ assertEquals(description2, testNameProviderForTesting.get());
+ }
+ });
+ startSecondTestFuture.get();
+
+ assertEquals(description1, testNameProviderForTesting.get());
+ testNameListener.testFinished(description1);
+ assertNull(testNameProviderForTesting.get());
+
+ Future<?> endSecondTestFuture =
+ executorService.submit(
+ new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(description2, testNameProviderForTesting.get());
+ try {
+ testNameListener.testFinished(description2);
+ } catch (Exception e) {
+ throwIfUnchecked(e);
+ throw new RuntimeException(e);
+ }
+ assertNull(testNameProviderForTesting.get());
+ }
+ });
+ endSecondTestFuture.get();
+
+ assertNull(testNameProviderForTesting.get());
+ }
+
+ /**
+ * Typically, {@link junit.framework.TestListener#startTest(junit.framework.Test)}
+ * and {@link junit.framework.TestListener#endTest(junit.framework.Test)}
+ * should be called in pairs, but if they're not for some reason, the
+ * listener will try to handle it as best as possible.
+ */
+ @Test
+ public void testJUnit4Listener_invalidStatesAreHandled() throws Exception {
+ testNameListener.testRunStarted(Description.createSuiteDescription(FakeTest.class));
+
+ Description description1 =
+ Description.createTestDescription(FakeTest.class, "methodName");
+ Description description2 =
+ Description.createTestDescription(FakeTest.class, "anotherMethodName");
+
+ testNameListener.testStarted(description1);
+ testNameListener.testStarted(description1);
+ assertEquals(description1, testNameProviderForTesting.get());
+
+ testNameListener.testStarted(description2);
+ assertEquals(description2, testNameProviderForTesting.get());
+
+ testNameListener.testFinished(description1);
+ assertNull(testNameProviderForTesting.get());
+
+ testNameListener.testFinished(description2);
+ assertNull(testNameProviderForTesting.get());
+ }
+
+
+ private static class FakeTest {
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestXmlListenerTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestXmlListenerTest.java
new file mode 100644
index 0000000000..11d35c7888
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/JUnit4TestXmlListenerTest.java
@@ -0,0 +1,288 @@
+// Copyright 2011 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.internal.junit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.Lists;
+import com.google.testing.junit.runner.internal.SignalHandlers;
+import com.google.testing.junit.runner.model.TestSuiteModel;
+import com.google.testing.junit.runner.util.Supplier;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.List;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
+
+/**
+ * Tests for {@link JUnit4TestXmlListener}
+ */
+@RunWith(JUnit4.class)
+public class JUnit4TestXmlListenerTest {
+ private static final String CHARSET = "UTF-8";
+ private final FakeSignalHandlers fakeSignalHandlers = new FakeSignalHandlers();
+ private final ByteArrayOutputStream errStream = new ByteArrayOutputStream();
+ private PrintStream errPrintStream;
+
+ @Before
+ public void createErrPrintStream() throws Exception {
+ errPrintStream = new PrintStream(errStream, true, CHARSET);
+ }
+
+ @Test
+ public void signalHandlerWritesXml() throws Exception {
+ TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class);
+ TestSuiteModel mockModel = mock(TestSuiteModel.class);
+ CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class);
+ OutputStream mockXmlStream = mock(OutputStream.class);
+ JUnit4TestXmlListener listener = new JUnit4TestXmlListener(
+ mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream);
+
+ Request request = Request.classWithoutSuiteMethod(PassingTest.class);
+ Description suiteDescription = request.getRunner().getDescription();
+
+ when(mockModelSupplier.get()).thenReturn(mockModel);
+
+ listener.testRunStarted(suiteDescription);
+ assertEquals(1, fakeSignalHandlers.handlers.size());
+
+ fakeSignalHandlers.handlers.get(0).handle(new Signal("TERM"));
+
+ String errOutput = errStream.toString(CHARSET);
+ assertTrue("expected signal name in stderr", errOutput.contains("SIGTERM"));
+ assertTrue("expected message in stderr", errOutput.contains("Done writing test XML"));
+
+ InOrder inOrder = inOrder(mockRequestFactory, mockModel);
+ inOrder.verify(mockRequestFactory).cancelRun();
+ inOrder.verify(mockModel).testRunInterrupted();
+ inOrder.verify(mockModel).writeAsXml(mockXmlStream);
+ }
+
+ @Test
+ public void writesXmlAtTestEnd() throws Exception {
+ TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class);
+ TestSuiteModel mockModel = mock(TestSuiteModel.class);
+ CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class);
+ OutputStream mockXmlStream = mock(OutputStream.class);
+ JUnit4TestXmlListener listener = new JUnit4TestXmlListener(
+ mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream);
+
+ when(mockModelSupplier.get()).thenReturn(mockModel);
+
+ JUnitCore core = new JUnitCore();
+ core.addListener(listener);
+ core.run(Request.classWithoutSuiteMethod(PassingTest.class));
+
+ assertEquals("no output to stderr expected", 0, errStream.size());
+ verify(mockModel).writeAsXml(mockXmlStream);
+ verify(mockRequestFactory, never()).cancelRun();
+ }
+
+ @Test
+ public void assumptionViolationsAreReportedAsSkippedTests() throws Exception {
+ TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class);
+ TestSuiteModel mockModel = mock(TestSuiteModel.class);
+ CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class);
+ OutputStream mockXmlStream = mock(OutputStream.class);
+ JUnit4TestXmlListener listener = new JUnit4TestXmlListener(
+ mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream);
+
+ Request request = Request.classWithoutSuiteMethod(TestWithAssumptionViolation.class);
+ Description suiteDescription = request.getRunner().getDescription();
+ Description testDescription = suiteDescription.getChildren().get(0);
+
+ when(mockModelSupplier.get()).thenReturn(mockModel);
+
+ JUnitCore core = new JUnitCore();
+ core.addListener(listener);
+ core.run(request);
+
+ assertEquals("no output to stderr expected", 0, errStream.size());
+ InOrder inOrder = inOrder(mockModel);
+ inOrder.verify(mockModel).testSkipped(testDescription);
+ inOrder.verify(mockModel).writeAsXml(mockXmlStream);
+ verify(mockRequestFactory, never()).cancelRun();
+ }
+
+ @Test
+ public void assumptionViolationsAtSuiteLevelAreReportedAsSkippedSuite() throws Exception {
+ TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class);
+ TestSuiteModel mockModel = mock(TestSuiteModel.class);
+ CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class);
+ OutputStream mockXmlStream = mock(OutputStream.class);
+ JUnit4TestXmlListener listener = new JUnit4TestXmlListener(
+ mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream);
+
+ Request request = Request.classWithoutSuiteMethod(
+ TestWithAssumptionViolationOnTheSuiteLevel.class);
+ Description suiteDescription = request.getRunner().getDescription();
+
+ when(mockModelSupplier.get()).thenReturn(mockModel);
+
+ JUnitCore core = new JUnitCore();
+ core.addListener(listener);
+ core.run(request);
+
+ assertEquals("no output to stderr expected", 0, errStream.size());
+ InOrder inOrder = inOrder(mockModel);
+ inOrder.verify(mockModel).testSkipped(suiteDescription);
+ inOrder.verify(mockModel).writeAsXml(mockXmlStream);
+ verify(mockRequestFactory, never()).cancelRun();
+ }
+
+ @Test
+ public void failuresAreReported() throws Exception {
+ TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class);
+ TestSuiteModel mockModel = mock(TestSuiteModel.class);
+ CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class);
+ OutputStream mockXmlStream = mock(OutputStream.class);
+ JUnit4TestXmlListener listener = new JUnit4TestXmlListener(
+ mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream);
+
+ Request request = Request.classWithoutSuiteMethod(FailingTest.class);
+ Description suiteDescription = request.getRunner().getDescription();
+ Description testDescription = suiteDescription.getChildren().get(0);
+
+ when(mockModelSupplier.get()).thenReturn(mockModel);
+
+ JUnitCore core = new JUnitCore();
+ core.addListener(listener);
+ core.run(request);
+
+ assertEquals("no output to stderr expected", 0, errStream.size());
+ InOrder inOrder = inOrder(mockModel);
+ inOrder.verify(mockModel).testFailure(eq(testDescription), any(Throwable.class));
+ inOrder.verify(mockModel).writeAsXml(mockXmlStream);
+ verify(mockRequestFactory, never()).cancelRun();
+ }
+
+ @Test
+ public void ignoredTestAreReportedAsSuppressedTests() throws Exception {
+ TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class);
+ TestSuiteModel mockModel = mock(TestSuiteModel.class);
+ CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class);
+ OutputStream mockXmlStream = mock(OutputStream.class);
+ JUnit4TestXmlListener listener = new JUnit4TestXmlListener(
+ mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream);
+
+ Request request = Request.classWithoutSuiteMethod(TestWithIgnoredTestCase.class);
+ Description suiteDescription = request.getRunner().getDescription();
+ Description testDescription = suiteDescription.getChildren().get(0);
+
+ when(mockModelSupplier.get()).thenReturn(mockModel);
+
+ JUnitCore core = new JUnitCore();
+ core.addListener(listener);
+ core.run(request);
+
+ assertEquals("no output to stderr expected", 0, errStream.size());
+ InOrder inOrder = inOrder(mockModel);
+ inOrder.verify(mockModel).testSuppressed(testDescription);
+ inOrder.verify(mockModel).writeAsXml(mockXmlStream);
+ verify(mockRequestFactory, never()).cancelRun();
+ }
+
+ /**
+ * Test with a method that always passes.
+ */
+ public static class PassingTest {
+ @Test
+ public void alwaysPasses() {
+ }
+ }
+
+
+ /**
+ * Test with a method that always fails.
+ */
+ public static class FailingTest {
+ @Test
+ public void alwaysFails() {
+ fail();
+ }
+ }
+
+
+ /**
+ * Test with a method that is always skipped.
+ */
+ public static class TestWithAssumptionViolation {
+ @Test
+ public void alwaysSkipped() {
+ assumeTrue(false);
+ }
+ }
+
+ /**
+ * Test with a method that is always skipped.
+ */
+ public static class TestWithAssumptionViolationOnTheSuiteLevel {
+ @BeforeClass
+ public static void failedSuiteLevelAssumption() {
+ assumeTrue(false);
+ }
+
+ @Test
+ public void fakeTest() {}
+ }
+
+ public static class TestWithIgnoredTestCase {
+ @Test
+ @Ignore
+ public void alwaysIgnored() {
+
+ }
+ }
+
+ private static class FakeSignalHandlers extends SignalHandlers {
+ public List<SignalHandler> handlers = Lists.newArrayList();
+
+ public FakeSignalHandlers() {
+ super(null);
+ }
+
+ @Override
+ public void installHandler(Signal signal, SignalHandler signalHandler) {
+ if (signal.getName().equals("TERM")) {
+ handlers.add(signalHandler);
+ }
+ }
+ }
+
+
+ private interface TestSuiteModelSupplier extends Supplier<TestSuiteModel> {
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/MemoizingRequestTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/MemoizingRequestTest.java
new file mode 100644
index 0000000000..a2818eb453
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/internal/junit4/MemoizingRequestTest.java
@@ -0,0 +1,73 @@
+// Copyright 2012 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.internal.junit4;
+
+import static org.mockito.Mockito.RETURNS_MOCKS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import junit.framework.TestCase;
+
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+
+/**
+ * Tests for {@code MemoizingRequest}.
+ */
+public class MemoizingRequestTest extends TestCase {
+ private Request mockRequestDelegate;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mockRequestDelegate = mock(Request.class, RETURNS_MOCKS);
+ }
+
+ public void testConstructorDoesNoWork() {
+ new MemoizingRequest(mockRequestDelegate);
+
+ verifyZeroInteractions(mockRequestDelegate);
+ }
+
+ public void testMemoizesRunner() {
+ MemoizingRequest memoizingRequest = new MemoizingRequest(mockRequestDelegate);
+
+ Runner firstRunner = memoizingRequest.getRunner();
+ Runner secondRunner = memoizingRequest.getRunner();
+
+ assertSame(firstRunner, secondRunner);
+ verify(mockRequestDelegate).getRunner();
+ verifyNoMoreInteractions(mockRequestDelegate);
+ }
+
+ public void testOverridingCreateRunner() {
+ final Runner stubRunner = mock(Runner.class);
+ MemoizingRequest memoizingRequest = new MemoizingRequest(mockRequestDelegate) {
+ @Override
+ protected Runner createRunner(Request delegate) {
+ return stubRunner;
+ }
+ };
+
+ Runner firstRunner = memoizingRequest.getRunner();
+ Runner secondRunner = memoizingRequest.getRunner();
+
+ assertSame(stubRunner, firstRunner);
+ assertSame(firstRunner, secondRunner);
+ verifyZeroInteractions(mockRequestDelegate);
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4BazelMock.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4BazelMock.java
new file mode 100644
index 0000000000..02c18746f4
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4BazelMock.java
@@ -0,0 +1,201 @@
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.internal.junit4.CancellableRequestFactory;
+import com.google.testing.junit.runner.model.AntXmlResultWriterFactory;
+import com.google.testing.junit.runner.model.TestSuiteModel;
+import com.google.testing.junit.runner.model.TestSuiteModelBuilderFactory;
+import com.google.testing.junit.runner.model.XmlResultWriter;
+import com.google.testing.junit.runner.sharding.ShardingEnvironment;
+import com.google.testing.junit.runner.sharding.ShardingFilters;
+import com.google.testing.junit.runner.util.MemoizingSupplier;
+import com.google.testing.junit.runner.util.SetFactory;
+import com.google.testing.junit.runner.util.Supplier;
+import com.google.testing.junit.runner.util.Ticker;
+import java.io.PrintStream;
+import java.util.Set;
+import org.junit.internal.TextListener;
+import org.junit.runner.Request;
+import org.junit.runner.notification.RunListener;
+
+/**
+ * Utility class to create a JUnit4Runner instance from a {@link Builder} for testing purposes. All
+ * required dependencies are being injected automatically.
+ */
+public final class JUnit4BazelMock {
+ private Supplier<Class<?>> topLevelSuiteSupplier;
+
+ private Supplier<Request> requestMemoizingSupplier;
+
+ private Supplier<CancellableRequestFactory> cancellableRequestFactorySupplier;
+
+ private Supplier<String> topLevelSuiteNameSupplier;
+
+ private Supplier<Ticker> tickerSupplier;
+
+ private Supplier<ShardingEnvironment> shardingEnvironmentSupplier;
+
+ private Supplier<ShardingFilters> shardingFiltersSupplier;
+
+ private Supplier<XmlResultWriter> xmlResultWriterSupplier;
+
+ private Supplier<TestSuiteModel.Builder> builderSupplier;
+
+ private Supplier<JUnit4TestModelBuilder> jUnit4TestModelBuilderMemoizingSupplier;
+
+ private Supplier<Supplier<TestSuiteModel>> provideTestSuiteModelSupplierMemoizingSupplier;
+
+ private Supplier<PrintStream> stdoutStreamMemoizingSupplier;
+
+ private Supplier<JUnit4Config> configSupplier;
+
+ private Supplier<Set<RunListener>> mockRunListenerSupplier;
+
+ private Supplier<TextListener> textListenerMemoizingSupplier;
+
+ private Supplier<RunListener> textListenerSupplier;
+
+ private Supplier<Set<RunListener>> setOfRunListenerSupplier;
+
+ private Supplier<JUnit4Runner> jUnit4RunnerProvider;
+
+ private JUnit4BazelMock(Builder builder) {
+ assert builder != null;
+ initialize(builder);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @SuppressWarnings("unchecked")
+ private void initialize(final Builder builder) {
+
+ this.topLevelSuiteSupplier = TopLevelSuiteFactory.create(builder.suiteClass);
+
+ this.requestMemoizingSupplier =
+ new MemoizingSupplier<>(RequestFactory.create(topLevelSuiteSupplier));
+
+ this.cancellableRequestFactorySupplier =
+ new MemoizingSupplier<>(CancellableRequestFactoryFactory.create());
+
+ this.topLevelSuiteNameSupplier = TopLevelSuiteNameFactory.create(topLevelSuiteSupplier);
+
+ this.tickerSupplier =
+ new MemoizingSupplier<>(TestModuleTickerFactory.create(builder.testModule));
+
+ this.shardingEnvironmentSupplier =
+ TestModuleShardingEnvironmentFactory.create(builder.testModule);
+
+ this.shardingFiltersSupplier =
+ TestModuleShardingFiltersFactory.create(
+ builder.testModule,
+ shardingEnvironmentSupplier,
+ ShardingFilterFactoryFactory.create());
+
+ this.xmlResultWriterSupplier =
+ TestModuleXmlResultWriterFactory.create(
+ builder.testModule, AntXmlResultWriterFactory.create());
+
+ this.builderSupplier =
+ TestSuiteModelBuilderFactory.create(
+ tickerSupplier,
+ shardingFiltersSupplier,
+ shardingEnvironmentSupplier,
+ xmlResultWriterSupplier);
+
+ this.jUnit4TestModelBuilderMemoizingSupplier =
+ new MemoizingSupplier<>(JUnit4TestModelBuilderFactory.create(
+ requestMemoizingSupplier, topLevelSuiteNameSupplier, builderSupplier));
+
+ this.provideTestSuiteModelSupplierMemoizingSupplier =
+ new MemoizingSupplier<>(TestSuiteModelSupplierFactory.create(
+ jUnit4TestModelBuilderMemoizingSupplier));
+
+ this.stdoutStreamMemoizingSupplier =
+ new MemoizingSupplier<>(TestModuleProvideStdoutStreamFactory.create(builder.testModule));
+
+ this.configSupplier = TestModuleConfigFactory.create(builder.testModule);
+
+ this.mockRunListenerSupplier =
+ TestModuleMockRunListenerFactory.create(builder.testModule);
+
+ this.textListenerMemoizingSupplier =
+ new MemoizingSupplier<>(ProvideTextListenerFactory.create(stdoutStreamMemoizingSupplier));
+
+ this.textListenerSupplier = TextListenerFactory.create(textListenerMemoizingSupplier);
+
+ this.setOfRunListenerSupplier =
+ SetFactory.<RunListener>builder(1, 1)
+ .addCollectionSupplier(mockRunListenerSupplier)
+ .addSupplier(textListenerSupplier)
+ .build();
+
+ this.jUnit4RunnerProvider =
+ JUnit4RunnerFactory.create(
+ requestMemoizingSupplier,
+ cancellableRequestFactorySupplier,
+ provideTestSuiteModelSupplierMemoizingSupplier,
+ stdoutStreamMemoizingSupplier,
+ configSupplier,
+ setOfRunListenerSupplier,
+ SetFactory.<JUnit4Runner.Initializer>empty());
+ }
+
+ public JUnit4Runner runner() {
+ return jUnit4RunnerProvider.get();
+ }
+
+ public CancellableRequestFactory cancellableRequestFactory() {
+ return cancellableRequestFactorySupplier.get();
+ }
+
+ public static final class Builder {
+ private JUnit4InstanceModules.SuiteClass suiteClass;
+
+ private JUnit4RunnerTest.TestModule testModule;
+
+ private Builder() {}
+
+ public JUnit4BazelMock build() {
+ if (suiteClass == null) {
+ throw new IllegalStateException(
+ JUnit4InstanceModules.SuiteClass.class.getCanonicalName() + " must be set");
+ }
+ if (testModule == null) {
+ throw new IllegalStateException(
+ JUnit4RunnerTest.TestModule.class.getCanonicalName() + " must be set");
+ }
+ return new JUnit4BazelMock(this);
+ }
+
+ public Builder testModule(JUnit4RunnerTest.TestModule testModule) {
+ if (testModule == null) {
+ throw new NullPointerException();
+ }
+ this.testModule = testModule;
+ return this;
+ }
+
+ public Builder suiteClass(JUnit4InstanceModules.SuiteClass suiteClass) {
+ if (suiteClass == null) {
+ throw new NullPointerException();
+ }
+ this.suiteClass = suiteClass;
+ return this;
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4ConfigTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4ConfigTest.java
new file mode 100644
index 0000000000..9ddc682657
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4ConfigTest.java
@@ -0,0 +1,118 @@
+// Copyright 2010 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.junit4;
+
+import static com.google.testing.junit.runner.junit4.JUnit4Config.JUNIT_API_VERSION_PROPERTY;
+import static com.google.testing.junit.runner.junit4.JUnit4Config.SHOULD_INSTALL_SECURITY_MANAGER_PROPERTY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.testing.junit.runner.util.GoogleTestSecurityManager;
+import java.util.Properties;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JUnit4Config}.
+ */
+@RunWith(JUnit4.class)
+public class JUnit4ConfigTest {
+
+ private JUnit4Config createConfigWithApiVersion(String apiVersion) {
+ Properties properties = new Properties();
+ properties.put(JUNIT_API_VERSION_PROPERTY, apiVersion);
+ return createConfigWithProperties(properties);
+ }
+
+ private JUnit4Config createConfigWithProperties(Properties properties) {
+ return new JUnit4Config("", null, null, properties);
+ }
+
+ @Test
+ public void testGetJUnitRunnerApiVersion_defaultValue() {
+ JUnit4Config config = createConfigWithApiVersion("1");
+ assertEquals(1, config.getJUnitRunnerApiVersion());
+ }
+
+ @Test
+ public void testGetJUnitRunnerApiVersion_failsIfNotNumeric() {
+ JUnit4Config config = createConfigWithApiVersion("I love pesto");
+
+ try {
+ config.getJUnitRunnerApiVersion();
+ fail("exception expected");
+ } catch (IllegalStateException expected) {
+ assertTrue(expected.getMessage().contains("I love pesto"));
+ }
+ }
+
+ @Test
+ public void testGetJUnitRunnerApiVersion_failsIfNotAnInteger() {
+ JUnit4Config config = createConfigWithApiVersion("3.14");
+
+ try {
+ config.getJUnitRunnerApiVersion();
+ fail("exception expected");
+ } catch (IllegalStateException expected) {
+ assertTrue(expected.getMessage().contains("3.14"));
+ }
+ }
+
+ @Test
+ public void testGetJUnitRunnerApiVersion_failsIfNotOne() {
+ JUnit4Config config = createConfigWithApiVersion("13");
+
+ try {
+ config.getJUnitRunnerApiVersion();
+ fail("exception expected");
+ } catch (IllegalStateException expected) {
+ assertTrue(expected.getMessage().contains("13"));
+ }
+ }
+
+ @Test
+ public void testGetJUnitRunnerApiVersion_oneIsValid() {
+ JUnit4Config config = createConfigWithApiVersion("1");
+ assertEquals(1, config.getJUnitRunnerApiVersion());
+ }
+
+ @Test
+ public void testShouldInstallSecurityManager_defaultValue() {
+ GoogleTestSecurityManager.uninstallIfInstalled();
+
+ JUnit4Config config = createConfigWithProperties(new Properties());
+ assertTrue(config.shouldInstallSecurityManager());
+ }
+
+ @Test
+ public void testShouldInstallSecurityManager_securityManagerPropertySet() {
+ Properties properties = new Properties();
+ properties.put("java.security.manager", "MySecurityManager");
+ properties.put(SHOULD_INSTALL_SECURITY_MANAGER_PROPERTY, "true");
+ JUnit4Config config = createConfigWithProperties(properties);
+ assertFalse(config.shouldInstallSecurityManager());
+ }
+
+ @Test
+ public void testShouldInstallSecurityManager_shouldInstallSecurityManagerPropertySetToFalse() {
+ Properties properties = new Properties();
+ properties.put(SHOULD_INSTALL_SECURITY_MANAGER_PROPERTY, "false");
+ JUnit4Config config = createConfigWithProperties(properties);
+ assertFalse(config.shouldInstallSecurityManager());
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4OptionsTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4OptionsTest.java
new file mode 100644
index 0000000000..699c5883bb
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4OptionsTest.java
@@ -0,0 +1,133 @@
+// Copyright 2011 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.junit4;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JUnit4Options}
+ */
+@RunWith(JUnit4.class)
+public class JUnit4OptionsTest {
+
+ private static final Map<String, String> EMPTY_ENV = Collections.emptyMap();
+
+ @Test
+ public void testParse_noArgs() throws Exception {
+ JUnit4Options options = JUnit4Options.parse(EMPTY_ENV, ImmutableList.<String>of());
+ assertNull(options.getTestIncludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+
+ @Test
+ public void testParse_onlyUnparsedArgs() {
+ JUnit4Options options = JUnit4Options.parse(EMPTY_ENV, ImmutableList.of("--bar", "baz"));
+ assertNull(options.getTestIncludeFilter());
+ assertArrayEquals(new String[] {"--bar", "baz"}, options.getUnparsedArgs());
+ }
+
+ @Test
+ public void testParse_withTwoArgTestFilter() throws Exception {
+ JUnit4Options options = JUnit4Options.parse(
+ EMPTY_ENV, ImmutableList.of("--test_filter", "foo"));
+ assertEquals("foo", options.getTestIncludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+
+ @Test
+ public void testParse_withOneArgTestFilter() throws Exception {
+ JUnit4Options options = JUnit4Options.parse(EMPTY_ENV, ImmutableList.of("--test_filter=foo"));
+ assertEquals("foo", options.getTestIncludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+
+ @Test
+ public void testParse_testFilterAndUnparsedArgs() throws Exception {
+ JUnit4Options options = JUnit4Options.parse(
+ EMPTY_ENV, ImmutableList.of("--bar", "--test_filter=foo", "--baz"));
+ assertEquals("foo", options.getTestIncludeFilter());
+ assertArrayEquals(new String[] {"--bar", "--baz"}, options.getUnparsedArgs());
+ }
+
+ @Test
+ public void testParse_testLastTestFilterWins() throws Exception {
+ JUnit4Options options =
+ JUnit4Options.parse(EMPTY_ENV, ImmutableList.of("--test_filter=foo", "--test_filter=bar"));
+ assertEquals("bar", options.getTestIncludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+
+ @Test
+ public void testParse_testFilterMissingSecondArg() throws Exception {
+ try {
+ JUnit4Options.parse(EMPTY_ENV, ImmutableList.of("--test_filter"));
+ fail();
+ } catch (RuntimeException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParse_testFilterExcludeWithTwoArgTestFilter() throws Exception {
+ JUnit4Options options = JUnit4Options.parse(
+ EMPTY_ENV, ImmutableList.of("--test_exclude_filter", "foo"));
+ assertEquals("foo", options.getTestExcludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+
+ @Test
+ public void testParse_testFilterExcludewithOneArgTestFilter() throws Exception {
+ JUnit4Options options = JUnit4Options.parse(
+ EMPTY_ENV, ImmutableList.of("--test_exclude_filter=foo"));
+ assertEquals("foo", options.getTestExcludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+
+ @Test
+ public void testParse_unknownOptionName() throws Exception {
+ JUnit4Options options = JUnit4Options.parse(
+ EMPTY_ENV, ImmutableList.of("--unknown=foo"));
+ assertArrayEquals(new String[] {"--unknown=foo"}, options.getUnparsedArgs());
+ }
+
+ @Test
+ public void testParse_withTestFilterFromEnv() throws Exception {
+ Map<String, String> env = new HashMap<>();
+ env.put("TESTBRIDGE_TEST_ONLY", "foo");
+ JUnit4Options options = JUnit4Options.parse(env, ImmutableList.<String>of());
+ assertEquals("foo", options.getTestIncludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+
+ @Test
+ public void testParse_testFilterArgOverridesEnv() throws Exception {
+ Map<String, String> env = new HashMap<>();
+ env.put("TESTBRIDGE_TEST_ONLY", "foo");
+ JUnit4Options options = JUnit4Options.parse(env, ImmutableList.of("--test_filter=bar"));
+ assertEquals("bar", options.getTestIncludeFilter());
+ assertEquals(0, options.getUnparsedArgs().length);
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4RunnerTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4RunnerTest.java
new file mode 100644
index 0000000000..6dd9bf32e2
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4RunnerTest.java
@@ -0,0 +1,628 @@
+// Copyright 2010 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.junit4;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.ByteStreams;
+import com.google.testing.junit.runner.internal.SignalHandlers.HandlerInstaller;
+import com.google.testing.junit.runner.internal.junit4.CancellableRequestFactory;
+import com.google.testing.junit.runner.internal.junit4.SettableCurrentRunningTest;
+import com.google.testing.junit.runner.junit4.JUnit4InstanceModules.SuiteClass;
+import com.google.testing.junit.runner.model.AntXmlResultWriter;
+import com.google.testing.junit.runner.model.XmlResultWriter;
+import com.google.testing.junit.runner.sharding.ShardingEnvironment;
+import com.google.testing.junit.runner.sharding.ShardingFilters;
+import com.google.testing.junit.runner.sharding.api.ShardingFilterFactory;
+import com.google.testing.junit.runner.sharding.testing.FakeShardingFilters;
+import com.google.testing.junit.runner.util.CurrentRunningTest;
+import com.google.testing.junit.runner.util.FakeTicker;
+import com.google.testing.junit.runner.util.GoogleTestSecurityManager;
+import com.google.testing.junit.runner.util.TestNameProvider;
+import com.google.testing.junit.runner.util.Ticker;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+import java.util.Set;
+import javax.annotation.Nullable;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.internal.TextListener;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.StoppedByUserException;
+import org.junit.runners.JUnit4;
+import org.junit.runners.Suite;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
+
+/**
+ * Tests for {@link JUnit4Runner}
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class JUnit4RunnerTest {
+ private final ByteArrayOutputStream stdoutByteStream = new ByteArrayOutputStream();
+ private final PrintStream stdoutPrintStream = new PrintStream(stdoutByteStream, true);
+ @Mock private RunListener mockRunListener;
+ @Mock private ShardingEnvironment shardingEnvironment = new StubShardingEnvironment();
+ @Mock private ShardingFilters shardingFilters;
+ private JUnit4Config config;
+ private boolean wasSecurityManagerInstalled = false;
+ private SecurityManager previousSecurityManager;
+
+ @After
+ public void closeStream() throws Exception {
+ stdoutPrintStream.close();
+ }
+
+ @After
+ public void reinstallPreviousSecurityManager() {
+ if (wasSecurityManagerInstalled) {
+ wasSecurityManagerInstalled = false;
+ System.setSecurityManager(previousSecurityManager);
+ }
+ }
+
+ private JUnit4Runner createRunner(Class<?> suiteClass) {
+ return createComponent(suiteClass).runner();
+ }
+
+ private JUnit4BazelMock createComponent(Class<?> suiteClass) {
+ return JUnit4BazelMock.builder()
+ .suiteClass(new SuiteClass(suiteClass))
+ .testModule(new TestModule()) // instance method to support outer-class instance variables.
+ .build();
+ }
+
+ @Test
+ public void testPassingTest() throws Exception {
+ config = createConfig();
+ mockRunListener = mock(RunListener.class);
+
+ JUnit4Runner runner = createRunner(SamplePassingTest.class);
+
+ Description testDescription =
+ Description.createTestDescription(SamplePassingTest.class, "testThatAlwaysPasses");
+ Description suiteDescription =
+ Description.createSuiteDescription(SamplePassingTest.class);
+ suiteDescription.addChild(testDescription);
+
+ Result result = runner.run();
+
+ assertEquals(1, result.getRunCount());
+ assertEquals(0, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+
+ assertPassingTestHasExpectedOutput(stdoutByteStream, SamplePassingTest.class);
+
+ InOrder inOrder = inOrder(mockRunListener);
+
+ inOrder.verify(mockRunListener).testRunStarted(suiteDescription);
+ inOrder.verify(mockRunListener).testStarted(testDescription);
+ inOrder.verify(mockRunListener).testFinished(testDescription);
+ inOrder.verify(mockRunListener).testRunFinished(any(Result.class));
+ }
+
+ @Test
+ public void testFailingTest() throws Exception {
+ config = createConfig();
+ mockRunListener = mock(RunListener.class);
+
+ JUnit4Runner runner = createRunner(SampleFailingTest.class);
+
+ Description testDescription = Description.createTestDescription(SampleFailingTest.class,
+ "testThatAlwaysFails");
+ Description suiteDescription = Description.createSuiteDescription(SampleFailingTest.class);
+ suiteDescription.addChild(testDescription);
+
+ Result result = runner.run();
+
+ assertEquals(1, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+
+ assertTrue(extractOutput(stdoutByteStream).contains(
+ "1) testThatAlwaysFails(" + SampleFailingTest.class.getName() + ")\n" +
+ "java.lang.AssertionError: expected"));
+
+ InOrder inOrder = inOrder(mockRunListener);
+
+ inOrder.verify(mockRunListener).testRunStarted(any(Description.class));
+ inOrder.verify(mockRunListener).testStarted(any(Description.class));
+ inOrder.verify(mockRunListener).testFailure(any(Failure.class));
+ inOrder.verify(mockRunListener).testFinished(any(Description.class));
+ inOrder.verify(mockRunListener).testRunFinished(any(Result.class));
+ }
+
+ @Test
+ public void testFailingInternationalCharsTest() throws Exception {
+ config = createConfig();
+ mockRunListener = mock(RunListener.class);
+
+ JUnit4Runner runner = createRunner(SampleInternationalFailingTest.class);
+
+ Description testDescription = Description.createTestDescription(
+ SampleInternationalFailingTest.class, "testFailingInternationalCharsTest");
+ Description suiteDescription = Description.createSuiteDescription(
+ SampleInternationalFailingTest.class);
+ suiteDescription.addChild(testDescription);
+
+ Result result = runner.run();
+
+ assertEquals(1, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+
+ String output = new String(stdoutByteStream.toByteArray(), StandardCharsets.UTF_8);
+ // Intentionally swapped "Test 日\u672C." / "Test \u65E5本." to make sure that the "raw"
+ // character does not get corrupted (would become ? in both cases and we would not notice).
+ assertTrue(output.contains("expected:<Test [Japan].> but was:<Test [日\u672C].>"));
+
+ InOrder inOrder = inOrder(mockRunListener);
+
+ inOrder.verify(mockRunListener).testRunStarted(any(Description.class));
+ inOrder.verify(mockRunListener).testStarted(any(Description.class));
+ inOrder.verify(mockRunListener).testFailure(any(Failure.class));
+ inOrder.verify(mockRunListener).testFinished(any(Description.class));
+ inOrder.verify(mockRunListener).testRunFinished(any(Result.class));
+ }
+
+ @Test
+ public void testInterruptedTest() throws Exception {
+ config = createConfig();
+ mockRunListener = mock(RunListener.class);
+ JUnit4BazelMock component = createComponent(SampleSuite.class);
+ JUnit4Runner runner = component.runner();
+ final CancellableRequestFactory requestFactory = component.cancellableRequestFactory();
+
+ Description testDescription = Description.createTestDescription(SamplePassingTest.class,
+ "testThatAlwaysPasses");
+
+ doAnswer(cancelTestRun(requestFactory))
+ .when(mockRunListener).testStarted(testDescription);
+
+ try {
+ runner.run();
+ fail("exception expected");
+ } catch (RuntimeException e) {
+ assertEquals("Test run interrupted", e.getMessage());
+ assertTrue("Expected cause to be a StoppedByUserException",
+ e.getCause() instanceof StoppedByUserException);
+
+ InOrder inOrder = inOrder(mockRunListener);
+ inOrder.verify(mockRunListener).testRunStarted(any(Description.class));
+ inOrder.verify(mockRunListener).testStarted(testDescription);
+ inOrder.verify(mockRunListener).testFinished(testDescription);
+ }
+ }
+
+ private static Answer<Void> cancelTestRun(final CancellableRequestFactory requestFactory) {
+ return new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ requestFactory.cancelRun();
+ return null;
+ }
+ };
+ }
+
+ @Test
+ public void testSecurityManagerInstalled() throws Exception {
+ // If there is already a security manager installed, the runner would crash when trying to
+ // install another one. In order to avoid that, the security manager should be uninstalled here
+ // and restored afterwards.
+ uninstallGoogleTestSecurityManager();
+
+ config = new JUnit4Config(null, null, null, createProperties("1", true));
+
+ JUnit4Runner runner = createRunner(SampleExitingTest.class);
+ Result result = runner.run();
+
+ assertEquals(1, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ }
+
+ @Test
+ public void testShardingIsSupported() {
+ config = createConfig();
+ shardingEnvironment = mock(ShardingEnvironment.class);
+ shardingFilters = new FakeShardingFilters(
+ Description.createTestDescription(SamplePassingTest.class, "testThatAlwaysPasses"),
+ Description.createTestDescription(SampleFailingTest.class, "testThatAlwaysFails"));
+
+ when(shardingEnvironment.isShardingEnabled()).thenReturn(true);
+
+ JUnit4Runner runner = createRunner(SampleSuite.class);
+ Result result = runner.run();
+
+ verify(shardingEnvironment).touchShardFile();
+
+ assertEquals(2, result.getRunCount());
+ if (result.getFailureCount() > 1) {
+ fail("Too many failures: " + result.getFailures());
+ }
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ assertEquals(2, runner.getModel().getNumTestCases());
+ }
+
+ @Test
+ public void testFilteringIsSupported() {
+ config = createConfig("testThatAlwaysFails");
+ JUnit4Runner runner = createRunner(SampleSuite.class);
+ Result result = runner.run();
+
+ assertEquals(1, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ assertEquals(
+ Description.createTestDescription(SampleFailingTest.class, "testThatAlwaysFails"),
+ result.getFailures().get(0).getDescription());
+ }
+
+ @Test
+ public void testRunFailsWithAllTestsFilteredOut() {
+ config = createConfig("doesNotMatchAnything");
+ JUnit4Runner runner = createRunner(SampleSuite.class);
+ Result result = runner.run();
+
+ assertEquals(1, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ assertTrue(result.getFailures().get(0).getMessage().contains("No tests found"));
+ }
+
+ @Test
+ public void testRunExcludeFilterAlwaysExits() {
+ config = new JUnit4Config("test", "CallsSystemExit", null, createProperties("1", false));
+ JUnit4Runner runner = createRunner(SampleSuite.class);
+ Result result = runner.run();
+
+ assertEquals(2, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ assertEquals(
+ Description.createTestDescription(SampleFailingTest.class, "testThatAlwaysFails"),
+ result.getFailures().get(0).getDescription());
+ }
+
+ @Test
+ public void testFilteringAndShardingTogetherIsSupported() {
+ config = createConfig("testThatAlways(Passes|Fails)");
+ shardingEnvironment = mock(ShardingEnvironment.class);
+ shardingFilters = new FakeShardingFilters(
+ Description.createTestDescription(SamplePassingTest.class, "testThatAlwaysPasses"),
+ Description.createTestDescription(SampleFailingTest.class, "testThatAlwaysFails"));
+
+ when(shardingEnvironment.isShardingEnabled()).thenReturn(true);
+
+ JUnit4Runner runner = createRunner(SampleSuite.class);
+ Result result = runner.run();
+
+ verify(shardingEnvironment).touchShardFile();
+
+ assertEquals(2, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ assertEquals(
+ Description.createTestDescription(SampleFailingTest.class, "testThatAlwaysFails"),
+ result.getFailures().get(0).getDescription());
+ }
+
+ @Test
+ public void testRunPassesWhenNoTestsOnCurrentShardWithFiltering() {
+ config = createConfig("testThatAlwaysFails");
+ shardingEnvironment = mock(ShardingEnvironment.class);
+ shardingFilters = new FakeShardingFilters(
+ Description.createTestDescription(SamplePassingTest.class, "testThatAlwaysPasses"));
+
+ when(shardingEnvironment.isShardingEnabled()).thenReturn(true);
+
+ JUnit4Runner runner = createRunner(SampleSuite.class);
+ Result result = runner.run();
+
+ verify(shardingEnvironment).touchShardFile();
+
+ assertEquals(0, result.getRunCount());
+ assertEquals(0, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ }
+
+ @Test
+ public void testRunFailsWhenNoTestsOnCurrentShardWithoutFiltering() {
+ config = createConfig();
+ shardingEnvironment = mock(ShardingEnvironment.class);
+ shardingFilters = mock(ShardingFilters.class);
+
+ when(shardingEnvironment.isShardingEnabled()).thenReturn(true);
+ when(shardingFilters.createShardingFilter(anyListOf(Description.class)))
+ .thenReturn(new NoneShallPassFilter());
+
+ JUnit4Runner runner = createRunner(SampleSuite.class);
+ Result result = runner.run();
+
+ assertEquals(1, result.getRunCount());
+ assertEquals(1, result.getFailureCount());
+ assertEquals(0, result.getIgnoreCount());
+ assertTrue(result.getFailures().get(0).getMessage().contains("No tests found"));
+
+ verify(shardingEnvironment).touchShardFile();
+ verify(shardingFilters).createShardingFilter(anyListOf(Description.class));
+ }
+
+ @Test
+ public void testMustSpecifySupportedJUnitApiVersion() {
+ config = new JUnit4Config(null, null, null, createProperties("2", false));
+ JUnit4Runner runner = createRunner(SamplePassingTest.class);
+
+ try {
+ runner.run();
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e.getMessage()).startsWith("Unsupported JUnit Runner API version");
+ }
+ }
+
+ /**
+ * Uninstall {@link GoogleTestSecurityManager} if it is installed. If it was installed, it will
+ * be reinstalled after the test completes.
+ */
+ private void uninstallGoogleTestSecurityManager() {
+ previousSecurityManager = System.getSecurityManager();
+ GoogleTestSecurityManager.uninstallIfInstalled();
+ if (previousSecurityManager != System.getSecurityManager()) {
+ wasSecurityManagerInstalled = true;
+ }
+ }
+
+ private void assertPassingTestHasExpectedOutput(ByteArrayOutputStream outputStream,
+ Class<?> testClass) {
+ ByteArrayOutputStream expectedOutputStream = getExpectedOutput(testClass);
+
+ assertEquals(extractOutput(expectedOutputStream), extractOutput(outputStream));
+ }
+
+ private String extractOutput(ByteArrayOutputStream outputStream) {
+ String output = new String(outputStream.toByteArray(), Charset.defaultCharset());
+ return output.replaceFirst("\nTime: .*\n", "\nTime: 0\n");
+ }
+
+ private ByteArrayOutputStream getExpectedOutput(Class<?> testClass) {
+ JUnitCore core = new JUnitCore();
+
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ PrintStream printStream = new PrintStream(byteStream);
+ printStream.println("JUnit4 Test Runner");
+ RunListener listener = new TextListener(printStream);
+ core.addListener(listener);
+
+ Request request = Request.classWithoutSuiteMethod(testClass);
+
+ core.run(request);
+ printStream.close();
+
+ return byteStream;
+ }
+
+ private static JUnit4Config createConfig() {
+ return createConfig(null);
+ }
+
+ private static JUnit4Config createConfig(@Nullable String includeFilter) {
+ return new JUnit4Config(includeFilter, null, null, createProperties("1", false));
+ }
+
+ private static Properties createProperties(
+ String apiVersion, boolean shouldInstallSecurityManager) {
+ Properties properties = new Properties();
+ properties.setProperty(JUnit4Config.JUNIT_API_VERSION_PROPERTY, apiVersion);
+ if (!shouldInstallSecurityManager) {
+ properties.setProperty("java.security.manager", "whatever");
+ }
+ return properties;
+ }
+
+ /** Sample test that passes. */
+ @RunWith(JUnit4.class)
+ public static class SamplePassingTest {
+
+ @Test
+ public void testThatAlwaysPasses() {
+ }
+ }
+
+
+ /** Sample test that fails. */
+ @RunWith(JUnit4.class)
+ public static class SampleFailingTest {
+
+ @Test
+ public void testThatAlwaysFails() {
+ org.junit.Assert.fail("expected");
+ }
+ }
+
+
+ /** Sample test that fails and shows international text without corrupting it. */
+ @RunWith(JUnit4.class)
+ public static class SampleInternationalFailingTest {
+
+ @Test
+ public void testThatAlwaysFails() {
+ assertEquals("Test Japan.", "Test \u65E5本.");
+ }
+ }
+
+
+ /** Sample test that calls System.exit(). */
+ @RunWith(JUnit4.class)
+ public static class SampleExitingTest {
+
+ @Test
+ public void testThatAlwaysCallsSystemExit() {
+ System.exit(1);
+ }
+ }
+
+
+ /** Sample suite. */
+ @RunWith(Suite.class)
+ @Suite.SuiteClasses({
+ JUnit4RunnerTest.SamplePassingTest.class,
+ JUnit4RunnerTest.SampleFailingTest.class,
+ JUnit4RunnerTest.SampleExitingTest.class
+ })
+ public static class SampleSuite {}
+
+
+ private static class StubShardingEnvironment extends ShardingEnvironment {
+
+ @Override
+ public boolean isShardingEnabled() {
+ return false;
+ }
+
+ @Override
+ public int getShardIndex() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getTotalShards() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void touchShardFile() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getTestShardingStrategy() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ /**
+ * Filter that won't run any tests.
+ */
+ private static class NoneShallPassFilter extends Filter {
+
+ @Override
+ public boolean shouldRun(Description description) {
+ return false;
+ }
+
+ @Override
+ public String describe() {
+ return "none-shall-pass filter";
+ }
+ }
+
+
+ private static class StubHandlerInstaller implements HandlerInstaller {
+
+ @Override
+ public SignalHandler install(Signal signal, SignalHandler handler) {
+ return null;
+ }
+ }
+
+
+ class TestModule {
+
+ ShardingEnvironment shardingEnvironment() {
+ return shardingEnvironment;
+ }
+
+ Ticker ticker() {
+ return new FakeTicker();
+ }
+
+ JUnit4Config config() {
+ return config;
+ }
+
+ HandlerInstaller handlerInstaller() {
+ return new StubHandlerInstaller();
+ }
+
+ OutputStream xmlOutputStream() {
+ return ByteStreams.nullOutputStream();
+ }
+
+ XmlResultWriter xmlResultWriter(AntXmlResultWriter impl) {
+ return impl;
+ }
+
+ Set<RunListener> mockRunListener() {
+ return (mockRunListener == null)
+ ? ImmutableSet.<RunListener>of()
+ : ImmutableSet.of(mockRunListener);
+ }
+
+ ShardingFilters shardingFilters(
+ ShardingEnvironment shardingEnvironment, ShardingFilterFactory defaultShardingStrategy) {
+ return (shardingFilters == null)
+ ? new ShardingFilters(shardingEnvironment, defaultShardingStrategy)
+ : shardingFilters;
+ }
+
+ PrintStream provideStdoutStream() {
+ return new PrintStream(stdoutByteStream);
+ }
+
+ PrintStream provideStderrStream() {
+ return new PrintStream(ByteStreams.nullOutputStream());
+ }
+
+ CurrentRunningTest provideCurrentRunningTest() {
+ return new SettableCurrentRunningTest() {
+ @Override
+ protected void setGlobalTestNameProvider(TestNameProvider provider) {
+ // Do not set the global current running test when the JUnit4Runner is being tested itself,
+ // in order not to override the real one.
+ }
+ };
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4TestModelBuilderTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4TestModelBuilderTest.java
new file mode 100644
index 0000000000..8a355842c2
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/JUnit4TestModelBuilderTest.java
@@ -0,0 +1,172 @@
+// Copyright 2010 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.junit4;
+
+import static com.google.testing.junit.runner.sharding.ShardingFilters.DEFAULT_SHARDING_STRATEGY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.Iterables;
+import com.google.testing.junit.runner.model.AntXmlResultWriter;
+import com.google.testing.junit.runner.model.TestNode;
+import com.google.testing.junit.runner.model.TestSuiteModel;
+import com.google.testing.junit.runner.model.XmlResultWriter;
+import com.google.testing.junit.runner.sharding.ShardingEnvironment;
+import com.google.testing.junit.runner.sharding.ShardingFilters;
+import com.google.testing.junit.runner.sharding.testing.StubShardingEnvironment;
+import com.google.testing.junit.runner.util.FakeTicker;
+import com.google.testing.junit.runner.util.Ticker;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.Request;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+/**
+ * Tests for {@code JUnit4TestModelBuilder}
+ */
+@RunWith(JUnit4.class)
+public class JUnit4TestModelBuilderTest {
+ private final Ticker fakeTicker = new FakeTicker();
+ private final ShardingEnvironment stubShardingEnvironment = new StubShardingEnvironment();
+ private final XmlResultWriter xmlResultWriter = new AntXmlResultWriter();
+
+ private JUnit4TestModelBuilder builder(Request request, String suiteName,
+ ShardingEnvironment shardingEnvironment, ShardingFilters shardingFilters,
+ XmlResultWriter xmlResultWriter) {
+ return new JUnit4TestModelBuilder(request, suiteName, new TestSuiteModel.Builder(
+ fakeTicker, shardingFilters, shardingEnvironment, xmlResultWriter));
+ }
+
+ @Test
+ public void testTouchesShardFileWhenShardingEnabled() {
+ Class<?> testClass = SampleTestCaseWithTwoTests.class;
+ Request request = Request.classWithoutSuiteMethod(testClass);
+ ShardingEnvironment mockShardingEnvironment = mock(ShardingEnvironment.class);
+ ShardingFilters shardingFilters = new ShardingFilters(
+ mockShardingEnvironment, DEFAULT_SHARDING_STRATEGY);
+ JUnit4TestModelBuilder modelBuilder = builder(
+ request, testClass.getCanonicalName(), mockShardingEnvironment, shardingFilters,
+ xmlResultWriter);
+
+ when(mockShardingEnvironment.isShardingEnabled()).thenReturn(true);
+ when(mockShardingEnvironment.getTotalShards()).thenReturn(2);
+ modelBuilder.get();
+
+ verify(mockShardingEnvironment).touchShardFile();
+ }
+
+ @Test
+ public void testDoesNotTouchShardFileWhenShardingDisabled() {
+ Class<?> testClass = SampleTestCaseWithTwoTests.class;
+ Request request = Request.classWithoutSuiteMethod(testClass);
+ ShardingEnvironment mockShardingEnvironment = mock(ShardingEnvironment.class);
+ ShardingFilters shardingFilters = new ShardingFilters(
+ mockShardingEnvironment, DEFAULT_SHARDING_STRATEGY);
+ JUnit4TestModelBuilder modelBuilder = builder(
+ request, testClass.getCanonicalName(), mockShardingEnvironment, shardingFilters,
+ xmlResultWriter);
+
+ when(mockShardingEnvironment.isShardingEnabled()).thenReturn(false);
+ modelBuilder.get();
+
+ verify(mockShardingEnvironment, never()).touchShardFile();
+ }
+
+ @Test
+ public void testCreateModel_singleTestClass() throws Exception {
+ Class<?> testClass = SampleTestCaseWithTwoTests.class;
+ Request request = Request.classWithoutSuiteMethod(testClass);
+ String testClassName = testClass.getCanonicalName();
+ JUnit4TestModelBuilder modelBuilder = builder(
+ request, testClassName, stubShardingEnvironment, null, xmlResultWriter);
+
+ Description suite = request.getRunner().getDescription();
+ Description testOne = suite.getChildren().get(0);
+ Description testTwo = suite.getChildren().get(1);
+
+ TestSuiteModel model = modelBuilder.get();
+ TestNode suiteNode = Iterables.getOnlyElement(model.getTopLevelTestSuites());
+ assertEquals(suite, suiteNode.getDescription());
+ List<TestNode> testCases = suiteNode.getChildren();
+ assertEquals(2, testCases.size());
+ TestNode testOneNode = testCases.get(0);
+ TestNode testTwoNode = testCases.get(1);
+ assertEquals(testOne, testOneNode.getDescription());
+ assertEquals(testTwo, testTwoNode.getDescription());
+ assertTrue(testOneNode.getChildren().isEmpty());
+ assertTrue(testTwoNode.getChildren().isEmpty());
+ assertEquals(2, model.getNumTestCases());
+ }
+
+ @Test
+ public void testCreateModel_simpleSuite() throws Exception {
+ Class<?> suiteClass = SampleSuite.class;
+ Request request = Request.classWithoutSuiteMethod(suiteClass);
+ String suiteClassName = suiteClass.getCanonicalName();
+ JUnit4TestModelBuilder modelBuilder = builder(
+ request, suiteClassName, stubShardingEnvironment, null, xmlResultWriter);
+
+ Description topSuite = request.getRunner().getDescription();
+ Description innerSuite = topSuite.getChildren().get(0);
+ Description testOne = innerSuite.getChildren().get(0);
+
+ TestSuiteModel model = modelBuilder.get();
+ TestNode topSuiteNode = Iterables.getOnlyElement(model.getTopLevelTestSuites());
+ assertEquals(topSuite, topSuiteNode.getDescription());
+ TestNode innerSuiteNode = Iterables.getOnlyElement(topSuiteNode.getChildren());
+ assertEquals(innerSuite, innerSuiteNode.getDescription());
+ TestNode testOneNode = Iterables.getOnlyElement(innerSuiteNode.getChildren());
+ assertEquals(testOne, testOneNode.getDescription());
+ assertTrue(testOneNode.getChildren().isEmpty());
+ assertEquals(1, model.getNumTestCases());
+ }
+
+
+ /** Sample test case with two tests. */
+ @RunWith(JUnit4.class)
+ public static class SampleTestCaseWithTwoTests {
+ @Test
+ public void testOne() {
+ }
+
+ @Test
+ public void testTwo() {
+ }
+ }
+
+
+ /** Sample test case with one test. */
+ @RunWith(JUnit4.class)
+ public static class SampleTestCaseWithOneTest {
+ @Test
+ public void testOne() {
+ }
+ }
+
+
+ /** Sample suite with one test. */
+ @RunWith(Suite.class)
+ @SuiteClasses(SampleTestCaseWithOneTest.class)
+ public static class SampleSuite {
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleConfigFactory.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleConfigFactory.java
new file mode 100644
index 0000000000..57f3074c09
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleConfigFactory.java
@@ -0,0 +1,42 @@
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.util.Factory;
+
+/**
+ * A factory that supplies {@link JUnit4Config} for testing purposes.
+ */
+public final class TestModuleConfigFactory implements Factory<JUnit4Config> {
+ private final JUnit4RunnerTest.TestModule module;
+
+ public TestModuleConfigFactory(JUnit4RunnerTest.TestModule module) {
+ assert module != null;
+ this.module = module;
+ }
+
+ @Override
+ public JUnit4Config get() {
+ JUnit4Config config = module.config();
+ if (config == null) {
+ throw new NullPointerException();
+ }
+ return config;
+ }
+
+ public static Factory<JUnit4Config> create(JUnit4RunnerTest.TestModule module) {
+ return new TestModuleConfigFactory(module);
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleMockRunListenerFactory.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleMockRunListenerFactory.java
new file mode 100644
index 0000000000..97b40e9f09
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleMockRunListenerFactory.java
@@ -0,0 +1,44 @@
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.util.Factory;
+import java.util.Set;
+import org.junit.runner.notification.RunListener;
+
+/**
+ * A factory that supplies a {@link Set}<{@link RunListener}> for testing purposes.
+ */
+public final class TestModuleMockRunListenerFactory implements Factory<Set<RunListener>> {
+ private final JUnit4RunnerTest.TestModule module;
+
+ public TestModuleMockRunListenerFactory(JUnit4RunnerTest.TestModule module) {
+ assert module != null;
+ this.module = module;
+ }
+
+ @Override
+ public Set<RunListener> get() {
+ Set<RunListener> runListeners = module.mockRunListener();
+ if (runListeners == null) {
+ throw new NullPointerException();
+ }
+ return runListeners;
+ }
+
+ public static Factory<Set<RunListener>> create(JUnit4RunnerTest.TestModule module) {
+ return new TestModuleMockRunListenerFactory(module);
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleProvideStdoutStreamFactory.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleProvideStdoutStreamFactory.java
new file mode 100644
index 0000000000..c7037bcc9d
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleProvideStdoutStreamFactory.java
@@ -0,0 +1,44 @@
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.util.Factory;
+import java.io.PrintStream;
+
+/**
+ * A factory that supplies a stdout {@link PrintStream} for testing purposes.
+ */
+public final class TestModuleProvideStdoutStreamFactory implements Factory<PrintStream> {
+ private final JUnit4RunnerTest.TestModule module;
+
+ public TestModuleProvideStdoutStreamFactory(
+ JUnit4RunnerTest.TestModule module) {
+ assert module != null;
+ this.module = module;
+ }
+
+ @Override
+ public PrintStream get() {
+ PrintStream printStream = module.provideStdoutStream();
+ if (printStream == null) {
+ throw new NullPointerException();
+ }
+ return printStream;
+ }
+
+ public static Factory<PrintStream> create(JUnit4RunnerTest.TestModule module) {
+ return new TestModuleProvideStdoutStreamFactory(module);
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingEnvironmentFactory.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingEnvironmentFactory.java
new file mode 100644
index 0000000000..ba5e4e27bf
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingEnvironmentFactory.java
@@ -0,0 +1,45 @@
+
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.sharding.ShardingEnvironment;
+import com.google.testing.junit.runner.util.Factory;
+
+/**
+ * A factory that supplies a {@link ShardingEnvironment} for testing purposes.
+ */
+public final class TestModuleShardingEnvironmentFactory implements Factory<ShardingEnvironment> {
+ private final JUnit4RunnerTest.TestModule module;
+
+ public TestModuleShardingEnvironmentFactory(
+ JUnit4RunnerTest.TestModule module) {
+ assert module != null;
+ this.module = module;
+ }
+
+ @Override
+ public ShardingEnvironment get() {
+ ShardingEnvironment shardingEnv = module.shardingEnvironment();
+ if (shardingEnv == null) {
+ throw new NullPointerException();
+ }
+ return shardingEnv;
+ }
+
+ public static Factory<ShardingEnvironment> create(JUnit4RunnerTest.TestModule module) {
+ return new TestModuleShardingEnvironmentFactory(module);
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingFiltersFactory.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingFiltersFactory.java
new file mode 100644
index 0000000000..144ed5dfe6
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleShardingFiltersFactory.java
@@ -0,0 +1,62 @@
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.sharding.ShardingEnvironment;
+import com.google.testing.junit.runner.sharding.ShardingFilters;
+import com.google.testing.junit.runner.sharding.api.ShardingFilterFactory;
+import com.google.testing.junit.runner.util.Factory;
+import com.google.testing.junit.runner.util.Supplier;
+
+/**
+ * A factory that supplies a {@link ShardingFilters} for testing purposes.
+ */
+public final class TestModuleShardingFiltersFactory implements Factory<ShardingFilters> {
+ private final JUnit4RunnerTest.TestModule module;
+
+ private final Supplier<ShardingEnvironment> shardingEnvironmentSupplier;
+
+ private final Supplier<ShardingFilterFactory> defaultShardingStrategySupplier;
+
+ public TestModuleShardingFiltersFactory(
+ JUnit4RunnerTest.TestModule module,
+ Supplier<ShardingEnvironment> shardingEnvironmentSupplier,
+ Supplier<ShardingFilterFactory> defaultShardingStrategySupplier) {
+ assert module != null;
+ this.module = module;
+ assert shardingEnvironmentSupplier != null;
+ this.shardingEnvironmentSupplier = shardingEnvironmentSupplier;
+ assert defaultShardingStrategySupplier != null;
+ this.defaultShardingStrategySupplier = defaultShardingStrategySupplier;
+ }
+
+ @Override
+ public ShardingFilters get() {
+ ShardingFilters shardingFilters = module.shardingFilters(
+ shardingEnvironmentSupplier.get(), defaultShardingStrategySupplier.get());
+ if (shardingFilters == null) {
+ throw new NullPointerException();
+ }
+ return shardingFilters;
+ }
+
+ public static Factory<ShardingFilters> create(
+ JUnit4RunnerTest.TestModule module,
+ Supplier<ShardingEnvironment> shardingEnvironmentSupplier,
+ Supplier<ShardingFilterFactory> defaultShardingStrategySupplier) {
+ return new TestModuleShardingFiltersFactory(
+ module, shardingEnvironmentSupplier, defaultShardingStrategySupplier);
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleTickerFactory.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleTickerFactory.java
new file mode 100644
index 0000000000..95376668a3
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleTickerFactory.java
@@ -0,0 +1,43 @@
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.util.Factory;
+import com.google.testing.junit.runner.util.Ticker;
+
+/**
+ * A factory that supplies a {@link Ticker} for testing purposes.
+ */
+public final class TestModuleTickerFactory implements Factory<Ticker> {
+ private final JUnit4RunnerTest.TestModule module;
+
+ public TestModuleTickerFactory(JUnit4RunnerTest.TestModule module) {
+ assert module != null;
+ this.module = module;
+ }
+
+ @Override
+ public Ticker get() {
+ Ticker ticker = module.ticker();
+ if (ticker == null) {
+ throw new NullPointerException();
+ }
+ return ticker;
+ }
+
+ public static Factory<Ticker> create(JUnit4RunnerTest.TestModule module) {
+ return new TestModuleTickerFactory(module);
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleXmlResultWriterFactory.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleXmlResultWriterFactory.java
new file mode 100644
index 0000000000..e0734d7554
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4/TestModuleXmlResultWriterFactory.java
@@ -0,0 +1,51 @@
+// Copyright 2016 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.junit4;
+
+import com.google.testing.junit.runner.model.AntXmlResultWriter;
+import com.google.testing.junit.runner.model.XmlResultWriter;
+import com.google.testing.junit.runner.util.Factory;
+import com.google.testing.junit.runner.util.Supplier;
+
+/**
+ * A factory that supplies a {@link XmlResultWriter} for testing purposes.
+ */
+public final class TestModuleXmlResultWriterFactory implements Factory<XmlResultWriter> {
+ private final JUnit4RunnerTest.TestModule module;
+
+ private final Supplier<AntXmlResultWriter> implSupplier;
+
+ public TestModuleXmlResultWriterFactory(
+ JUnit4RunnerTest.TestModule module, Supplier<AntXmlResultWriter> implSupplier) {
+ assert module != null;
+ this.module = module;
+ assert implSupplier != null;
+ this.implSupplier = implSupplier;
+ }
+
+ @Override
+ public XmlResultWriter get() {
+ XmlResultWriter resultWriter = module.xmlResultWriter(implSupplier.get());
+ if (resultWriter == null) {
+ throw new NullPointerException();
+ }
+ return resultWriter;
+ }
+
+ public static Factory<XmlResultWriter> create(
+ JUnit4RunnerTest.TestModule module, Supplier<AntXmlResultWriter> implSupplier) {
+ return new TestModuleXmlResultWriterFactory(module, implSupplier);
+ }
+} \ No newline at end of file
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestCaseNodeTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestCaseNodeTest.java
new file mode 100644
index 0000000000..ed313c1da8
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestCaseNodeTest.java
@@ -0,0 +1,146 @@
+// Copyright 2015 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.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit test for {@link TestCaseNode}.
+ */
+@RunWith(JUnit4.class)
+public class TestCaseNodeTest {
+
+ private static final long NOW = 1;
+ private static Description suite;
+ private static Description testCase;
+
+ @BeforeClass
+ public static void createDescriptions() {
+ suite = Description.createSuiteDescription(TestSuiteNode.class);
+ testCase = Description.createTestDescription(TestSuite.class, "testCase");
+ suite.addChild(testCase);
+ }
+
+ @Test
+ public void assertIsTestCase() {
+ assertTrue(new TestCaseNode(testCase, new TestSuiteNode(suite)).isTestCase());
+ }
+
+ @Test
+ public void assertIsSkippedIfNotStarted() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ assertStatusWithoutTiming(testCaseNode, TestResult.Status.SKIPPED);
+ }
+
+ @Test
+ public void assertIsCancelledIfInterruptedBeforeStart() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.testInterrupted(NOW);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.CANCELLED, NOW, 0);
+ }
+
+ @Test
+ public void assertIsCompletedIfFailedBeforeStart() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.testFailure(new Exception(), NOW);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.COMPLETED, NOW, 0);
+ }
+
+ @Test
+ public void assertInterruptedIfStartedAndNotFinished() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.started(NOW);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.INTERRUPTED, NOW, 0);
+ // Notice: This is an unexpected ending state, as even interrupted test executions should go
+ // through the testCaseNode.interrupted() code path.
+ }
+
+ @Test
+ public void assertInterruptedIfStartedAndInterrupted() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.started(NOW);
+ testCaseNode.testInterrupted(NOW + 1);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.INTERRUPTED, NOW, 1);
+ }
+
+ @Test
+ public void assertSkippedIfStartedAndSkipped() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.started(NOW);
+ testCaseNode.testSkipped(NOW + 1);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.SKIPPED, NOW, 1);
+ }
+
+ @Test
+ public void assertCompletedIfStartedAndFinished() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.started(NOW);
+ testCaseNode.finished(NOW + 1);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.COMPLETED, NOW, 1);
+ }
+
+ @Test
+ public void assertCompletedIfStartedAndFailedAndFinished() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.started(NOW);
+ testCaseNode.testFailure(new Exception(), NOW + 1);
+ testCaseNode.finished(NOW + 2);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.COMPLETED, NOW, 2);
+ }
+
+ @Test
+ public void assertInterruptedIfStartedAndFailedAndInterrupted() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.started(NOW);
+ testCaseNode.testFailure(new Exception(), NOW + 1);
+ testCaseNode.testInterrupted(NOW + 2);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.INTERRUPTED, NOW, 2);
+ }
+
+ @Test
+ public void assertTestSuppressedIfNotStartedAndSuppressed() {
+ TestCaseNode testCaseNode = new TestCaseNode(testCase, new TestSuiteNode(suite));
+ testCaseNode.testSuppressed(NOW);
+ assertStatusAndTiming(testCaseNode, TestResult.Status.SUPPRESSED, NOW, 0);
+ }
+
+ private void assertStatusAndTiming(
+ TestCaseNode testCase, TestResult.Status status, long start, long duration) {
+ TestResult result = testCase.getResult();
+ assertEquals(status, result.getStatus());
+ assertNotNull(result.getRunTimeInterval());
+ assertEquals(start, result.getRunTimeInterval().getStartMillis());
+ assertEquals(duration, result.getRunTimeInterval().toDurationMillis());
+ }
+
+ private void assertStatusWithoutTiming(TestCaseNode testCase, TestResult.Status status) {
+ TestResult result = testCase.getResult();
+ assertEquals(status, result.getStatus());
+ assertNull(result.getRunTimeInterval());
+ }
+
+ static class TestSuite {
+ @Test public void testCase() {}
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java
new file mode 100644
index 0000000000..ebab4a7cd5
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java
@@ -0,0 +1,65 @@
+// Copyright 2016 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.model;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Date;
+import java.util.TimeZone;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TestIntervalTest {
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testCreation() {
+ TestInterval interval = new TestInterval(123456, 234567);
+ assertEquals(123456, interval.getStartMillis());
+ assertEquals(234567, interval.getEndMillis());
+
+ interval = new TestInterval(123456, 123456);
+ assertEquals(123456, interval.getStartMillis());
+ assertEquals(123456, interval.getEndMillis());
+ }
+
+ @Test
+ public void testCreationFailure() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Start must be before end");
+ new TestInterval(35, 23);
+ }
+
+ @Test
+ public void testToDuration() {
+ assertEquals(100, new TestInterval(50, 150).toDurationMillis());
+ assertEquals(0, new TestInterval(100, 100).toDurationMillis());
+ }
+
+ @Test
+ public void testDateFormat() {
+ Date date = new Date(1471709734000L);
+ TestInterval interval = new TestInterval(date.getTime(), date.getTime() + 100);
+ assertEquals(
+ "2016-08-20T12:15:34.000-04:00",
+ interval.startInstantToString(TimeZone.getTimeZone("America/New_York")));
+ assertEquals(
+ "2016-08-20T16:15:34.000Z", interval.startInstantToString(TimeZone.getTimeZone("GMT")));
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestSuiteNodeTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestSuiteNodeTest.java
new file mode 100644
index 0000000000..61b97cdd6f
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestSuiteNodeTest.java
@@ -0,0 +1,86 @@
+// Copyright 2015 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.model;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+/**
+ * Unit test for {@link TestSuiteNode}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TestSuiteNodeTest {
+
+ private static final long NOW = 1;
+
+ @Mock private TestCaseNode testCaseNode;
+ private TestSuiteNode testSuiteNode;
+
+ @Before
+ public void createTestSuiteNode() {
+ testSuiteNode = new TestSuiteNode(Description.createSuiteDescription("suite"));
+ testSuiteNode.addTestCase(testCaseNode);
+ }
+
+ @Test
+ public void testIsTestCase() {
+ assertFalse(testSuiteNode.isTestCase());
+ verifyZeroInteractions(testCaseNode);
+ }
+
+ @Test
+ public void testInterrupted() {
+ testSuiteNode.testInterrupted(NOW);
+ verify(testCaseNode, times(1)).testInterrupted(NOW);
+ }
+
+ @Test
+ public void testTestSkipped() {
+ testSuiteNode.testSkipped(NOW);
+ verify(testCaseNode, times(1)).testSkipped(NOW);
+ }
+
+ @Test
+ public void testTestIgnored() {
+ testSuiteNode.testSuppressed(NOW);
+ verify(testCaseNode, times(1)).testSuppressed(NOW);
+ }
+
+ @Test
+ public void testTestFailure() {
+ Exception failure = new Exception();
+ testSuiteNode.testFailure(failure, NOW);
+ verify(testCaseNode, times(1)).testFailure(failure, NOW);
+ }
+
+ @Test
+ public void testDynamicFailure() {
+ Description dynamicTestCaseDescription = mock(Description.class);
+ Exception failure = new Exception();
+ testSuiteNode.dynamicTestFailure(dynamicTestCaseDescription, failure, NOW);
+ verify(testCaseNode, times(1)).dynamicTestFailure(dynamicTestCaseDescription, failure, NOW);
+ verifyZeroInteractions(dynamicTestCaseDescription);
+ }
+
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/XmlWriterTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/XmlWriterTest.java
new file mode 100644
index 0000000000..423d1f4f3d
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/XmlWriterTest.java
@@ -0,0 +1,232 @@
+// Copyright 2010 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.model;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.base.Joiner;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link XmlWriter}
+ */
+@RunWith(JUnit4.class)
+public class XmlWriterTest {
+ private static final Joiner LINE_JOINER = Joiner.on(XmlWriter.EOL);
+ private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ @Rule
+ public final ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void encodingShouldBeUtf8() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("String");
+ String utf8String = "z\u0080\u0800\u010000"; // 1+2+3+4 bytes
+ xmlWriter.writeCharacters(utf8String);
+ xmlWriter.close();
+
+ // Note: assertHasContents() reads the bytes of the outputStream as a UTF-8 string
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<String>" + utf8String,
+ "</String>");
+ }
+
+ @Test
+ public void header() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>");
+ }
+
+ @Test
+ public void emptyDocument() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("DocumentName");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<DocumentName />");
+ }
+
+ @Test
+ public void emptyDocumentWithOneAttribute() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Properties");
+ xmlWriter.writeAttribute("name", "value");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Properties name='value' />");
+ }
+
+ @Test
+ public void emptyDocumentWithTwoAttributes() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("TestSuite");
+ xmlWriter.writeAttribute("count", 7);
+ xmlWriter.writeAttribute("size", "large");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<TestSuite count='7' size='large' />");
+ }
+
+ @Test
+ public void emptyDocumentWithThreeAttributes() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("TestSuite");
+ xmlWriter.writeAttribute("count", 7);
+ xmlWriter.writeAttribute("size", "large");
+ xmlWriter.writeAttribute("time", 1.0);
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<TestSuite count='7' size='large' time='1.0' />");
+ }
+
+ @Test
+ public void documentWithOneEmptyElement() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Root");
+ xmlWriter.writeAttribute("childCount", 1);
+ xmlWriter.startElement("Child");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Root childCount='1'>",
+ " <Child />",
+ "</Root>");
+ }
+
+ @Test
+ public void documentWithOneEmptyElementWithAttribute() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Root");
+ xmlWriter.startElement("Child");
+ xmlWriter.writeAttribute("name", "value");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Root>",
+ " <Child name='value' />",
+ "</Root>");
+ }
+
+ @Test
+ public void documentWithOneElementWithCharactersNoEscaping()
+ throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Root");
+ xmlWriter.startElement("Child");
+ xmlWriter.writeCharacters("some text\nmore text");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Root>",
+ " <Child>some text",
+ "more text",
+ " </Child>",
+ "</Root>");
+ }
+
+ @Test
+ public void documentWithOneElementWithCharactersNeedingEscaping()
+ throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Root");
+ xmlWriter.startElement("Child");
+ xmlWriter.writeCharacters("foo]]>bar");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Root>",
+ " <Child>foo]]&gt;bar",
+ " </Child>",
+ "</Root>");
+ }
+
+ @Test
+ public void documentWithOneElementChild() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Root");
+ xmlWriter.startElement("Child");
+ xmlWriter.writeAttribute("name", "value");
+ xmlWriter.startElement("Grandchild");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Root>",
+ " <Child name='value'>",
+ " <Grandchild />",
+ " </Child>",
+ "</Root>");
+ }
+
+ @Test
+ public void documentWithTwoElements() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Parent");
+ xmlWriter.startElement("Child");
+ xmlWriter.writeAttribute("name", "Deanna");
+ xmlWriter.endElement();
+ xmlWriter.startElement("Child");
+ xmlWriter.writeAttribute("name", "Kyle");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Parent>",
+ " <Child name='Deanna' />",
+ " <Child name='Kyle' />",
+ "</Parent>");
+ }
+
+ @Test
+ public void attributeValuesEscaped() throws Exception {
+ XmlWriter xmlWriter = new XmlWriter(outputStream);
+ xmlWriter.startDocument();
+ xmlWriter.startElement("Expression");
+ xmlWriter.writeAttribute("name", "a > b");
+ xmlWriter.close();
+
+ assertHasContents("<?xml version='1.0' encoding='UTF-8'?>",
+ "<Expression name='a &gt; b' />");
+ }
+
+ private void assertHasContents(String... contents) throws UnsupportedEncodingException {
+ Object[] expected = contents;
+
+ assertEquals(LINE_JOINER.join(expected).trim(), outputStream.toString("UTF-8").trim());
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/HashBackedShardingFilterTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/HashBackedShardingFilterTest.java
new file mode 100644
index 0000000000..8ae46f7272
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/HashBackedShardingFilterTest.java
@@ -0,0 +1,42 @@
+// Copyright 2010 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.sharding;
+
+import com.google.testing.junit.runner.sharding.api.ShardingFilterFactory;
+import com.google.testing.junit.runner.sharding.testing.ShardingFilterTestCase;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+
+import java.util.Collection;
+
+/**
+ * Tests for the {@link HashBackedShardingFilter}.
+ */
+public class HashBackedShardingFilterTest extends ShardingFilterTestCase {
+
+ private static class HashBackedShardingFilterFactory implements ShardingFilterFactory {
+ @Override
+ public Filter createFilter(
+ Collection<Description> testDescriptions, int shardIndex, int totalShards) {
+ return new HashBackedShardingFilter(shardIndex, totalShards);
+ }
+ }
+
+ @Override
+ protected ShardingFilterFactory createShardingFilterFactory() {
+ return new HashBackedShardingFilterFactory();
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/RoundRobinShardingFilterTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/RoundRobinShardingFilterTest.java
new file mode 100644
index 0000000000..5aa55aa467
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/RoundRobinShardingFilterTest.java
@@ -0,0 +1,61 @@
+// Copyright 2010 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.sharding;
+
+import com.google.testing.junit.runner.sharding.api.ShardingFilterFactory;
+import com.google.testing.junit.runner.sharding.testing.RoundRobinShardingFilterFactory;
+import com.google.testing.junit.runner.sharding.testing.ShardingFilterTestCase;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tests for the {@link RoundRobinShardingFilter}.
+ */
+public class RoundRobinShardingFilterTest extends ShardingFilterTestCase {
+
+ private static final List<Description> GENERIC_TEST_DESCRIPTIONS =
+ ShardingFilterTestCase.createGenericTestCaseDescriptions(6);
+
+ private static final List<Filter> FILTERS_1 =
+ createFilters(GENERIC_TEST_DESCRIPTIONS, 3, new RoundRobinShardingFilterFactory());
+ private static final List<Filter> FILTERS_2 =
+ createFilters(GENERIC_TEST_DESCRIPTIONS, 4, new RoundRobinShardingFilterFactory());
+
+ public void testShardingIsBalanced() {
+ Map<Filter, List<Description>> run1 = simulateTestRun(FILTERS_1, GENERIC_TEST_DESCRIPTIONS);
+ assertEquals(2, run1.get(FILTERS_1.get(0)).size());
+ assertEquals(2, run1.get(FILTERS_1.get(1)).size());
+ assertEquals(2, run1.get(FILTERS_1.get(2)).size());
+
+ Map<Filter, List<Description>> run2 = simulateTestRun(FILTERS_2, GENERIC_TEST_DESCRIPTIONS);
+ assertEquals(2, run2.get(FILTERS_2.get(0)).size());
+ assertEquals(2, run2.get(FILTERS_2.get(1)).size());
+ assertEquals(1, run2.get(FILTERS_2.get(2)).size());
+ assertEquals(1, run2.get(FILTERS_2.get(3)).size());
+ }
+
+ public void testShouldRun_throwsExceptionForUnknownDescription() {
+ assertThrowsExceptionForUnknownDescription(FILTERS_1.get(0));
+ }
+
+ @Override
+ protected ShardingFilterFactory createShardingFilterFactory() {
+ return new RoundRobinShardingFilterFactory();
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingEnvironmentTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingEnvironmentTest.java
new file mode 100644
index 0000000000..b8ab333ca2
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingEnvironmentTest.java
@@ -0,0 +1,45 @@
+// Copyright 2010 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.sharding;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.devtools.build.lib.testutil.TestUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import java.io.File;
+
+/**
+ * Tests interactions with the test environment related to sharding.
+ */
+@RunWith(JUnit4.class)
+public class ShardingEnvironmentTest {
+
+ @SuppressWarnings({"ResultOfMethodCallIgnored"})
+ @Test
+ public void testTouchShardingFile() {
+ File shardFile = new File(TestUtils.tmpDirFile(), "shard_file_123");
+ assertFalse(shardFile.exists());
+ try {
+ ShardingEnvironment.touchShardFile(shardFile);
+ assertTrue(shardFile.exists());
+ } finally {
+ shardFile.delete();
+ }
+ }
+
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingFiltersTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingFiltersTest.java
new file mode 100644
index 0000000000..ec55f91a56
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/sharding/ShardingFiltersTest.java
@@ -0,0 +1,94 @@
+// Copyright 2010 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.sharding;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import com.google.testing.junit.runner.sharding.api.ShardingFilterFactory;
+import com.google.testing.junit.runner.sharding.testing.ShardingFilterTestCase;
+import java.util.Collection;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runner.manipulation.Filter;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+/**
+ * Tests for {@link ShardingFilters}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ShardingFiltersTest {
+ @Mock ShardingEnvironment mockShardingEnvironment;
+
+ @Test
+ public void testCreateShardingFilter_defaultStrategy() {
+ List<Description> descriptions = ShardingFilterTestCase.createGenericTestCaseDescriptions(6);
+ RoundRobinShardingFilter expectedFilter = new RoundRobinShardingFilter(descriptions, 0, 5);
+
+ when(mockShardingEnvironment.getShardIndex()).thenReturn(0);
+ when(mockShardingEnvironment.getTotalShards()).thenReturn(5);
+ when(mockShardingEnvironment.getTestShardingStrategy()).thenReturn(null);
+
+ ShardingFilters shardingFilters = new ShardingFilters(mockShardingEnvironment,
+ ShardingFilters.ShardingStrategy.ROUND_ROBIN);
+ Filter filter = shardingFilters.createShardingFilter(descriptions);
+
+ assertThat(filter).isInstanceOf(RoundRobinShardingFilter.class);
+ RoundRobinShardingFilter shardingFilter = (RoundRobinShardingFilter) filter;
+ assertEquals(expectedFilter.testToShardMap, shardingFilter.testToShardMap);
+ assertEquals(expectedFilter.shardIndex, shardingFilter.shardIndex);
+ assertEquals(expectedFilter.totalShards, shardingFilter.totalShards);
+ }
+
+ @Test
+ public void testCreateShardingFilter_customStrategy() {
+ List<Description> descriptions = ShardingFilterTestCase.createGenericTestCaseDescriptions(6);
+
+ when(mockShardingEnvironment.getShardIndex()).thenReturn(0);
+ when(mockShardingEnvironment.getTotalShards()).thenReturn(5);
+ when(mockShardingEnvironment.getTestShardingStrategy()).thenReturn(
+ "com.google.testing.junit.runner.sharding.ShardingFiltersTest$TestFilterFactory");
+
+ ShardingFilters shardingFilters = new ShardingFilters(mockShardingEnvironment);
+ Filter filter = shardingFilters.createShardingFilter(descriptions);
+
+ assertEquals("com.google.testing.junit.runner.sharding.ShardingFiltersTest.TestFilter",
+ filter.getClass().getCanonicalName());
+ }
+
+ public static class TestFilterFactory implements ShardingFilterFactory {
+ @Override
+ public Filter createFilter(
+ Collection<Description> testDescriptions, int shardIndex, int totalShards) {
+ return new TestFilter();
+ }
+ }
+
+ static class TestFilter extends Filter {
+ @Override
+ public boolean shouldRun(Description description) {
+ return false;
+ }
+
+ @Override
+ public String describe() {
+ return "test filter factory";
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD
new file mode 100644
index 0000000000..2bb65e1643
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD
@@ -0,0 +1,24 @@
+DEFAULT_VISIBILITY = [
+ "//src/java_tools/junitrunner:__subpackages__",
+]
+
+package(default_visibility = DEFAULT_VISIBILITY)
+
+licenses(["notice"]) # Apache 2.0
+
+java_library(
+ name = "testbed",
+ testonly = 1,
+ srcs = glob(["*.java"]),
+ deps = [
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["*.java"]) + ["BUILD"],
+ visibility = ["//src:__pkg__"],
+)
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/ExampleObject.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/ExampleObject.java
new file mode 100644
index 0000000000..e6d66cf460
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/ExampleObject.java
@@ -0,0 +1,64 @@
+// Copyright 2015 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.testbed;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * A sample class that is under test by XmlOutputExercises.
+ */
+public class ExampleObject implements Comparable<ExampleObject> {
+ private String data;
+
+ public ExampleObject(String data) {
+ this.data = Preconditions.checkNotNull(data);
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = Preconditions.checkNotNull(data);
+ }
+
+ @Override
+ public int compareTo(ExampleObject that) {
+ return this.data.compareTo(that.data);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ExampleObject that = (ExampleObject) o;
+ return data.equals(that.data);
+ }
+
+ @Override
+ public int hashCode() {
+ return data.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return this.data;
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/Fifo.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/Fifo.java
new file mode 100644
index 0000000000..26fb73ad05
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/Fifo.java
@@ -0,0 +1,41 @@
+// Copyright 2015 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.testbed;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Utility class to synchronize test bed tests and shell tests using a FIFO file.
+ */
+public final class Fifo {
+ private static final String FIFO = System.getProperty("test.fifo");
+
+ private Fifo(){}
+
+ /**
+ * Helper method to help with the synchronization between testbed java test and shell tests. It
+ * will block until data is available on the FIFO
+ */
+ static void waitUntilDataAvailable() throws IOException {
+ if (FIFO == null) {
+ throw new IllegalStateException("No fifo specified");
+ }
+ Files.asByteSource(new File(FIFO)).copyTo(ByteStreams.nullOutputStream());
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/InternationalCharsTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/InternationalCharsTest.java
new file mode 100644
index 0000000000..ee7979ee74
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/InternationalCharsTest.java
@@ -0,0 +1,27 @@
+// Copyright 2015 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.testbed;
+
+import junit.framework.TestCase;
+
+/**
+ * This is a testbed for testing UTF8 test-log functionality.
+ * Failures in this test should not cause continuous builds to go red.
+ */
+public class InternationalCharsTest extends TestCase {
+ public void testThatAlwaysFails() {
+ assertEquals("Test Japan.", "Test \u65E5本.");
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/JUnit4TestbridgeExercises.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/JUnit4TestbridgeExercises.java
new file mode 100644
index 0000000000..cd575262fd
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/JUnit4TestbridgeExercises.java
@@ -0,0 +1,36 @@
+// Copyright 2015 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.testbed;
+
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * A JUnit4-style test meant to be invoked by junit4_testbridge_tests.sh.
+ */
+@RunWith(JUnit4.class)
+public class JUnit4TestbridgeExercises {
+ @Test
+ public void doRun() {
+ }
+
+ @Test
+ public void doNotRun() {
+ fail();
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/StackTraceExercises.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/StackTraceExercises.java
new file mode 100644
index 0000000000..e9c34100ef
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/StackTraceExercises.java
@@ -0,0 +1,53 @@
+// Copyright 2010 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.testbed;
+
+import junit.framework.TestCase;
+
+/**
+ * This is a testbed for testing stack trace functionality.
+ * Failures in this test should not cause continuous builds to go red.
+ */
+public class StackTraceExercises extends TestCase {
+
+ /**
+ * Succeeds fast but leaves behind a devious shutdown hook designed to wreak havoc.
+ */
+ public void testSneakyShutdownHook() throws Exception {
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ public void run() {
+ handleHook();
+ }});
+ }
+
+ private static void handleHook() {
+ try {
+ System.out.println("Entered shutdown hook");
+ System.out.flush();
+ Fifo.waitUntilDataAvailable();
+ Thread.sleep(15000);
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * A test which invokes System.exit(0). Bad test!
+ */
+ public void testNotSoFastBuddy() {
+ System.out.println("Hey, not so fast there");
+ System.exit(0);
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/SuiteMethodTakesForever.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/SuiteMethodTakesForever.java
new file mode 100644
index 0000000000..e0d6bde9b3
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/SuiteMethodTakesForever.java
@@ -0,0 +1,41 @@
+// Copyright 2015 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.testbed;
+
+import junit.framework.Test;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This is a testbed for testing stack trace functionality when the test runner is interrupted
+ * with a TERM signal during the test suite creation phase.
+ *
+ * <p>Failures in this test should not cause continuous builds to go red.
+ */
+public class SuiteMethodTakesForever {
+
+ /**
+ * Simulates a test suite that takes a really long time to build, giving enough time to the
+ * test to send the TERM signal and verify the output.
+ */
+ public static Test suite() throws Exception {
+ System.out.println("Entered suite creation");
+ System.out.flush();
+ Fifo.waitUntilDataAvailable();
+ TimeUnit.HOURS.sleep(1);
+ throw new IllegalStateException(
+ "Expected to be interrupted before finishing the suite creation");
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/XmlOutputExercises.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/XmlOutputExercises.java
new file mode 100644
index 0000000000..09de3a8b59
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/XmlOutputExercises.java
@@ -0,0 +1,111 @@
+// Copyright 2015 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.testbed;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+
+/**
+ * This is a testbed for testing XML output functionality.
+ */
+@RunWith(Enclosed.class)
+public class XmlOutputExercises {
+
+ /**
+ * A sample test class testing .compareTo()
+ */
+ public static class ComparabilityTest {
+ private ExampleObject exampleObject;
+
+ @Before
+ public void setUp() throws Exception {
+ exampleObject = new ExampleObject("example");
+ }
+
+ @Test
+ public void compareToEqualInstance() throws Exception {
+ ExampleObject test = new ExampleObject("example");
+ assertThat(test).isEquivalentAccordingToCompareTo(exampleObject);
+ }
+
+ @Test
+ public void compareToGreaterInstance() throws Exception {
+ ExampleObject test = new ExampleObject("gxample");
+ assertThat(test).isGreaterThan(exampleObject);
+ }
+
+ @Test
+ public void compareToLessInstance() throws Exception {
+ ExampleObject test = new ExampleObject("axample");
+ assertThat(test).isLessThan(exampleObject);
+ }
+ }
+
+ /**
+ * A sample test class testing .equals() and .hashCode()
+ */
+ public static class EqualsHashCodeTest {
+ private ExampleObject exampleObject;
+
+ @Before
+ public void setUp() throws Exception {
+ exampleObject = new ExampleObject("example");
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ assertThat(new ExampleObject("example")).isEqualTo(exampleObject);
+ assertThat(new ExampleObject("wrong")).isNotEqualTo(exampleObject);
+ }
+
+ @Test
+ public void testHashCode() throws Exception {
+ assertThat(exampleObject.hashCode()).isEqualTo("example".hashCode());
+ }
+ }
+
+ /**
+ * A sample test class testing .toString()
+ */
+ public static class OtherTests {
+ private ExampleObject exampleObject;
+
+ @Before
+ public void setUp() throws Exception {
+ exampleObject = new ExampleObject("example");
+ }
+
+ @Test
+ public void testToString() {
+ assertThat(exampleObject.toString()).isEqualTo("example");
+ }
+ }
+
+
+ /**
+ * A sample test class testing failures
+ */
+ public static class FailureTest {
+ @Test
+ public void testFail() {
+ fail("This is an expected error. The test is supposed to fail.");
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/GoogleTestSecurityManagerTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/GoogleTestSecurityManagerTest.java
new file mode 100644
index 0000000000..ab0c704a2e
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/GoogleTestSecurityManagerTest.java
@@ -0,0 +1,160 @@
+// Copyright 2002 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.util;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.security.Permission;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test the GoogleTestSecurityManager. Most of the tests only works if the
+ * security manager is actually installed; otherwise they just
+ * pass without testing anything.
+ */
+@RunWith(JUnit4.class)
+public class GoogleTestSecurityManagerTest {
+ private SecurityManager previousSecurityManager;
+ private GoogleTestSecurityManager installedSecurityManager;
+
+ @Before
+ public void setUp() throws Exception {
+ previousSecurityManager = System.getSecurityManager();
+
+ // These tests assume that there isn't already a GoogleTestSecurityManager
+ // running.
+ GoogleTestSecurityManager.uninstallIfInstalled();
+ }
+
+ @After
+ public void tearDown() {
+ if (installedSecurityManager != null) {
+ installedSecurityManager.setEnabled(false);
+ }
+ if (System.getSecurityManager() != previousSecurityManager) {
+ System.setSecurityManager(previousSecurityManager);
+ }
+ }
+
+ private void installTestSecurityManager() {
+ SecurityManager previousSecurityManager = System.getSecurityManager();
+ assertNull(previousSecurityManager);
+
+ installedSecurityManager = new GoogleTestSecurityManager();
+ System.setSecurityManager(installedSecurityManager);
+ }
+
+ @Test
+ public void testExit() {
+ installTestSecurityManager();
+
+ try {
+ System.exit(1);
+ fail("exit() have thrown exception; how come it didn't exit?!");
+ } catch (SecurityException se) {
+ // passed
+ }
+ }
+
+ @Test
+ public void testSetSecurityManager() {
+ installTestSecurityManager();
+
+ try {
+ System.setSecurityManager(new SecurityManager());
+ fail("setSecurityManager() should have thrown exception.");
+ } catch (SecurityException se) {
+ // passed
+ }
+ }
+
+ /**
+ * test enabling/disabling the security manager. This test does not require
+ * that a GoogleTestSecurityManager be installed.
+ */
+ @Test
+ public void testSecurityManagerEnabled() {
+ // create a security manager to use, but don't install it.
+ GoogleTestSecurityManager sm = new GoogleTestSecurityManager();
+
+ assertTrue(sm.isEnabled());
+ try {
+ sm.checkExit(0);
+ fail("GoogleTestSecurityManager allowed exit while enabled.");
+ } catch (SecurityException ex) {
+ // passed
+ }
+
+ sm.setEnabled(false);
+ assertTrue(!sm.isEnabled());
+
+ sm.checkExit(0); // should allow
+
+ sm.setEnabled(true);
+ assertTrue(sm.isEnabled());
+ try {
+ sm.checkExit(0);
+ fail("GoogleTestSecurityManager allowed exit while enabled.");
+ } catch (SecurityException ex) {
+ // passed
+ }
+ }
+
+ @Test
+ public void testUninstallIfInstalled_whenInstalled() {
+ installTestSecurityManager();
+ GoogleTestSecurityManager.uninstallIfInstalled();
+
+ assertTrue("Security manager should be enabled", installedSecurityManager.isEnabled());
+ assertNull("Security manager should be uninstalled", System.getSecurityManager());
+ }
+
+ @Test
+ public void testUninstallIfInstalled_whenNoSecurityManagerInstalled() {
+ GoogleTestSecurityManager.uninstallIfInstalled();
+
+ assertNull("No security manager should be uninstalled", System.getSecurityManager());
+ }
+
+ @Test
+ public void testUninstallIfInstalled_whenOtherSecurityManagerInstalled() {
+ PermissiveSecurityManager otherSecurityManager = new PermissiveSecurityManager();
+ System.setSecurityManager(otherSecurityManager);
+ GoogleTestSecurityManager.uninstallIfInstalled();
+
+ assertSame(otherSecurityManager, System.getSecurityManager());
+ System.setSecurityManager(null);
+ }
+
+ /**
+ * Security manager that allows anything.
+ */
+ private static class PermissiveSecurityManager extends SecurityManager {
+ @Override public void checkPermission(Permission p) {
+ return;
+ }
+
+ @Override public void checkPermission(Permission p, java.lang.Object o) {
+ return;
+ }
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestIntegrationsExporterTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestIntegrationsExporterTest.java
new file mode 100644
index 0000000000..01ffb641ad
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestIntegrationsExporterTest.java
@@ -0,0 +1,58 @@
+// Copyright 2011 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.util;
+
+import static org.mockito.Mockito.verify;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+/** Tests for {@link TestIntegrationsExporter}. */
+@RunWith(MockitoJUnitRunner.class)
+public class TestIntegrationsExporterTest {
+ @Mock private TestIntegrationsExporter.Callback mockCallback;
+ private TestIntegrationsExporter.Callback previousCallback;
+
+ @Before
+ public void setThreadCallback() throws Exception {
+ previousCallback = TestIntegrationsRunnerIntegration.setTestCaseForThread(mockCallback);
+ }
+
+ @After
+ public void restorePreviousThreadCallback() {
+ TestIntegrationsRunnerIntegration.setTestCaseForThread(previousCallback);
+ }
+
+ @Test
+ public void testExportTestIntegration() {
+ final TestIntegration testIntegration =
+ TestIntegration.builder()
+ .setContactEmail("test@testmail.com")
+ .setComponentId("1234")
+ .setName("Test")
+ .setUrl("testurl")
+ .setDescription("Test description.")
+ .setForegroundColor("white")
+ .setBackgroundColor("rgb(47, 122, 243)")
+ .build();
+
+ TestIntegrationsExporter.INSTANCE.newTestIntegration(testIntegration);
+ verify(mockCallback).exportTestIntegration(testIntegration);
+ }
+}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestPropertyExporterTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestPropertyExporterTest.java
new file mode 100644
index 0000000000..b467e263dc
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/util/TestPropertyExporterTest.java
@@ -0,0 +1,67 @@
+// Copyright 2011 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.util;
+
+import static org.mockito.Mockito.verify;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+/**
+ * Tests for {@link TestPropertyExporter}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TestPropertyExporterTest {
+ @Mock private TestPropertyExporter.Callback mockCallback;
+ private TestPropertyExporter.Callback previousCallback;
+
+ @Before
+ public void setThreadCallback() throws Exception {
+ previousCallback = TestPropertyRunnerIntegration.setTestCaseForThread(mockCallback);
+ }
+
+ @After
+ public void restorePreviousThreadCallback() throws Exception {
+ TestPropertyRunnerIntegration.setTestCaseForThread(previousCallback);
+ }
+
+ @Test
+ public void testExportProperty() {
+ TestPropertyExporter.INSTANCE.exportProperty("propertyName", "value");
+ verify(mockCallback).exportProperty("propertyName", "value");
+ }
+
+ @Test
+ public void testExportRepeatedProperty() {
+ TestPropertyExporter.INSTANCE.exportRepeatedProperty("propertyName", "value");
+ verify(mockCallback).exportRepeatedProperty("propertyName", "value");
+ }
+
+ @Test
+ public void testExportProperty_emptyNameIsValid() {
+ TestPropertyExporter.INSTANCE.exportProperty(" ", "value");
+ verify(mockCallback).exportProperty(" ", "value");
+ }
+
+ @Test
+ public void testExportRepeatedProperty_emptyNameIsValid() {
+ TestPropertyExporter.INSTANCE.exportRepeatedProperty(" ", "value");
+ verify(mockCallback).exportRepeatedProperty(" ", "value");
+ }
+}