aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal')
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/BUILD18
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/SignalHandlers.java81
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/StackTraces.java152
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stderr.java31
-rw-r--r--src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stdout.java31
5 files changed, 313 insertions, 0 deletions
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/BUILD b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/BUILD
new file mode 100644
index 0000000000..696fd36cea
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/BUILD
@@ -0,0 +1,18 @@
+package(default_visibility = ["//src:__subpackages__"])
+
+java_library(
+ name = "internal",
+ srcs = glob(["*.java"]),
+ deps = [
+ "//third_party:guava",
+ "//third_party:guice",
+ "//third_party:joda_time",
+ "//third_party:jsr305",
+ "//third_party:junit4",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/SignalHandlers.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/SignalHandlers.java
new file mode 100644
index 0000000000..c1573d5a78
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/SignalHandlers.java
@@ -0,0 +1,81 @@
+// 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 com.google.inject.Inject;
+
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Helper class to install signal handlers.
+ */
+public class SignalHandlers {
+ private final HandlerInstaller handlerInstaller;
+
+ /**
+ * Creates a handler installer that installs signal handlers.
+ */
+ public static HandlerInstaller createRealHandlerInstaller() {
+ return new HandlerInstaller() {
+ @Override
+ public SignalHandler install(Signal signal, SignalHandler handler) {
+ return Signal.handle(signal, handler);
+ }
+ };
+ }
+
+ @Inject
+ public SignalHandlers(HandlerInstaller installer) {
+ this.handlerInstaller = installer;
+ }
+
+ /**
+ * Adds the given signal handler to the existing ones.
+ *
+ * <p>Signal handlers are responsible to catch any exception if the following
+ * handlers need to be executed when a handler throws an exception.
+ *
+ * @param signal The signal to handle.
+ * @param signalHandler The handler to install.
+ */
+ public void installHandler(Signal signal, final SignalHandler signalHandler) {
+ final AtomicReference<SignalHandler> previousHandlerReference =
+ new AtomicReference<>();
+ previousHandlerReference.set(handlerInstaller.install(signal, new SignalHandler() {
+ @Override
+ public void handle(Signal signal) {
+ signalHandler.handle(signal);
+ SignalHandler previousHandler = previousHandlerReference.get();
+ if (previousHandler != null) {
+ previousHandler.handle(signal);
+ }
+ }
+ }));
+ }
+
+ /**
+ * Wraps sun.misc.Signal#handle(sun.misc.Signal, sun.misc.SignalHandler)
+ * to help with testing.
+ */
+ public interface HandlerInstaller {
+ /**
+ * @see sun.misc.Signal#handle(sun.misc.Signal, sun.misc.SignalHandler)
+ */
+ SignalHandler install(Signal signal, SignalHandler handler);
+ }
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/StackTraces.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/StackTraces.java
new file mode 100644
index 0000000000..37695061eb
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/StackTraces.java
@@ -0,0 +1,152 @@
+// 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;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+import java.io.PrintStream;
+import java.lang.management.LockInfo;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * Utilities for stack traces.
+ */
+public class StackTraces {
+
+ /**
+ * Prints all stack traces to the given stream.
+ *
+ * @param out Stream to print to
+ */
+ public static void printAll(PrintStream out) {
+ out.println("Starting full thread dump ...\n");
+ ThreadMXBean mb = ManagementFactory.getThreadMXBean();
+
+ // ThreadInfo has comprehensive information such as locks.
+ ThreadInfo[] threadInfos = mb.dumpAllThreads(true, true);
+
+ // But we can know whether a thread is daemon only from Thread
+ Set<Thread> threads = Thread.getAllStackTraces().keySet();
+ ImmutableMap<Long, Thread> threadMap = Maps.uniqueIndex(
+ threads, new Function<Thread, Long>() {
+ @Override public Long apply(Thread thread) {
+ return thread.getId();
+ }
+ });
+
+ // Dump non-daemon threads first
+ for (ThreadInfo threadInfo : threadInfos) {
+ Thread thread = threadMap.get(threadInfo.getThreadId());
+ if (thread != null && !thread.isDaemon()) {
+ dumpThreadInfo(threadInfo, thread, out);
+ }
+ }
+
+ // Dump daemon threads
+ for (ThreadInfo threadInfo : threadInfos) {
+ Thread thread = threadMap.get(threadInfo.getThreadId());
+ if (thread != null && thread.isDaemon()) {
+ dumpThreadInfo(threadInfo, thread, out);
+ }
+ }
+
+ long[] deadlockedThreads = mb.findDeadlockedThreads();
+ if (deadlockedThreads != null) {
+ out.println("Detected deadlocked threads: " +
+ Arrays.toString(deadlockedThreads));
+ }
+ long[] monitorDeadlockedThreads = mb.findMonitorDeadlockedThreads();
+ if (monitorDeadlockedThreads != null) {
+ out.println("Detected monitor deadlocked threads: " +
+ Arrays.toString(monitorDeadlockedThreads));
+ }
+ out.println("\nDone full thread dump.");
+ out.flush();
+ }
+
+ // Adopted from ThreadInfo.toString(), without MAX_FRAMES limit
+ private static void dumpThreadInfo(ThreadInfo t, Thread thread, PrintStream out) {
+ out.print("\"" + t.getThreadName() + "\"" +
+ " Id=" + t.getThreadId() + " " +
+ t.getThreadState());
+ if (t.getLockName() != null) {
+ out.print(" on " + t.getLockName());
+ }
+ if (t.getLockOwnerName() != null) {
+ out.print(" owned by \"" + t.getLockOwnerName() +
+ "\" Id=" + t.getLockOwnerId());
+ }
+ if (t.isSuspended()) {
+ out.print(" (suspended)");
+ }
+ if (t.isInNative()) {
+ out.print(" (in native)");
+ }
+ if (thread.isDaemon()) {
+ out.print(" (daemon)");
+ }
+ out.print('\n');
+ StackTraceElement[] stackTrace = t.getStackTrace();
+ MonitorInfo[] lockedMonitors = t.getLockedMonitors();
+ for (int i = 0; i < stackTrace.length; i++) {
+ StackTraceElement ste = stackTrace[i];
+ out.print("\tat " + ste.toString());
+ out.print('\n');
+ if (i == 0 && t.getLockInfo() != null) {
+ Thread.State ts = t.getThreadState();
+ switch (ts) {
+ case BLOCKED:
+ out.print("\t- blocked on " + t.getLockInfo());
+ out.print('\n');
+ break;
+ case WAITING:
+ out.print("\t- waiting on " + t.getLockInfo());
+ out.print('\n');
+ break;
+ case TIMED_WAITING:
+ out.print("\t- waiting on " + t.getLockInfo());
+ out.print('\n');
+ break;
+ default:
+ }
+ }
+
+ for (MonitorInfo mi : lockedMonitors) {
+ if (mi.getLockedStackDepth() == i) {
+ out.print("\t- locked " + mi);
+ out.print('\n');
+ }
+ }
+ }
+
+ LockInfo[] locks = t.getLockedSynchronizers();
+ if (locks.length > 0) {
+ out.print("\n\tNumber of locked synchronizers = " + locks.length);
+ out.print('\n');
+ for (LockInfo li : locks) {
+ out.print("\t- " + li);
+ out.print('\n');
+ }
+ }
+ out.print('\n');
+ }
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stderr.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stderr.java
new file mode 100644
index 0000000000..80b37eb0d0
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stderr.java
@@ -0,0 +1,31 @@
+// 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;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Binding annotation for a {@link java.io.PrintStream} printing to stderr.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@BindingAnnotation
+public @interface Stderr {
+}
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stdout.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stdout.java
new file mode 100644
index 0000000000..051968bc98
--- /dev/null
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal/Stdout.java
@@ -0,0 +1,31 @@
+// 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.internal;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Binding annotation for a {@link java.io.PrintStream} printing to stdout.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@BindingAnnotation
+public @interface Stdout {
+}