diff options
Diffstat (limited to 'src/java_tools/junitrunner/java/com/google/testing/junit/runner/internal')
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 { +} |