/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.twitter.distributedlog;

import java.io.PrintWriter;
import java.io.StringWriter;
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.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

/**
 * JUnit run listener which prints full thread dump into System.err in case a test is failed due to
 * timeout.
 */
public class TimedOutTestsListener extends RunListener {

    static final String TEST_TIMED_OUT_PREFIX = "test timed out after";

    private static String indent = "    ";

    private final PrintWriter output;

    public TimedOutTestsListener() {
        this.output = new PrintWriter(System.err);
    }

    public TimedOutTestsListener(PrintWriter output) {
        this.output = output;
    }

    @Override
    public void testFailure(Failure failure) throws Exception {
        if (failure != null && failure.getMessage() != null && failure.getMessage().startsWith(TEST_TIMED_OUT_PREFIX)) {
            output.println("====> TEST TIMED OUT. PRINTING THREAD DUMP. <====");
            output.println();
            output.print(buildThreadDiagnosticString());
        }
    }

    public static String buildThreadDiagnosticString() {
        StringWriter sw = new StringWriter();
        PrintWriter output = new PrintWriter(sw);

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss,SSS");
        output.println(String.format("Timestamp: %s", dateFormat.format(new Date())));
        output.println();
        output.println(buildThreadDump());

        String deadlocksInfo = buildDeadlockInfo();
        if (deadlocksInfo != null) {
            output.println("====> DEADLOCKS DETECTED <====");
            output.println();
            output.println(deadlocksInfo);
        }

        return sw.toString();
    }

    static String buildThreadDump() {
        StringBuilder dump = new StringBuilder();
        Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
        for (Map.Entry<Thread, StackTraceElement[]> e : stackTraces.entrySet()) {
            Thread thread = e.getKey();
            dump.append(String.format("\"%s\" %s prio=%d tid=%d %s\njava.lang.Thread.State: %s", thread.getName(),
                (thread.isDaemon() ? "daemon" : ""), thread.getPriority(), thread.getId(),
                Thread.State.WAITING.equals(thread.getState()) ? "in Object.wait()"
                        : StringUtils.lowerCase(thread.getState().name()),
                Thread.State.WAITING.equals(thread.getState()) ? "WAITING (on object monitor)" : thread.getState()));
            for (StackTraceElement stackTraceElement : e.getValue()) {
                dump.append("\n        at ");
                dump.append(stackTraceElement);
            }
            dump.append("\n");
        }
        return dump.toString();
    }

    static String buildDeadlockInfo() {
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        long[] threadIds = threadBean.findMonitorDeadlockedThreads();
        if (threadIds != null && threadIds.length > 0) {
            StringWriter stringWriter = new StringWriter();
            PrintWriter out = new PrintWriter(stringWriter);

            ThreadInfo[] infos = threadBean.getThreadInfo(threadIds, true, true);
            for (ThreadInfo ti : infos) {
                printThreadInfo(ti, out);
                printLockInfo(ti.getLockedSynchronizers(), out);
                out.println();
            }

            out.close();
            return stringWriter.toString();
        } else {
            return null;
        }
    }

    private static void printThreadInfo(ThreadInfo ti, PrintWriter out) {
        // print thread information
        printThread(ti, out);

        // print stack trace with locks
        StackTraceElement[] stacktrace = ti.getStackTrace();
        MonitorInfo[] monitors = ti.getLockedMonitors();
        for (int i = 0; i < stacktrace.length; i++) {
            StackTraceElement ste = stacktrace[i];
            out.println(indent + "at " + ste.toString());
            for (MonitorInfo mi : monitors) {
                if (mi.getLockedStackDepth() == i) {
                    out.println(indent + "  - locked " + mi);
                }
            }
        }
        out.println();
    }

    private static void printThread(ThreadInfo ti, PrintWriter out) {
        out.print("\"" + ti.getThreadName() + "\"" + " Id=" + ti.getThreadId() + " in " + ti.getThreadState());
        if (ti.getLockName() != null) {
            out.print(" on lock=" + ti.getLockName());
        }
        if (ti.isSuspended()) {
            out.print(" (suspended)");
        }
        if (ti.isInNative()) {
            out.print(" (running in native)");
        }
        out.println();
        if (ti.getLockOwnerName() != null) {
            out.println(indent + " owned by " + ti.getLockOwnerName() + " Id=" + ti.getLockOwnerId());
        }
    }

    private static void printLockInfo(LockInfo[] locks, PrintWriter out) {
        out.println(indent + "Locked synchronizers: count = " + locks.length);
        for (LockInfo li : locks) {
            out.println(indent + "  - " + li);
        }
        out.println();
    }

}