/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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 art;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.CountDownLatch;
import java.util.function.Function;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.time.Instant;

public class Test924 {
  public static void run() throws Exception {
    // Run the test on its own thread, so we have a known state for the "current" thread.
    Thread t = new Thread("TestThread") {
      @Override
      public void run() {
        try {
          doTest();
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    };
    t.start();
    t.join();
  }

  private static void doTest() throws Exception {
    Thread t1 = Thread.currentThread();
    Thread t2 = getCurrentThread();

    // Need to adjust priority, as on-device this may be unexpected (and we prefer not
    // to special-case this.)
    t1.setPriority(5);

    if (t1 != t2) {
      throw new RuntimeException("Expected " + t1 + " but got " + t2);
    }
    System.out.println("currentThread OK");

    printThreadInfo(t1);
    printThreadInfo(null);

    Thread t3 = new Thread("Daemon Thread");
    t3.setDaemon(true);
    // Do not start this thread, yet.
    printThreadInfo(t3);
    // Start, and wait for it to die.
    t3.start();
    t3.join();
    Thread.sleep(500);  // Wait a little bit.
    // Thread has died, check that we can still get info.
    printThreadInfo(t3);

    // Try a subclass of thread.
    Thread t4 = new Thread("Subclass") {
    };
    printThreadInfo(t4);

    doCurrentThreadStateTests();
    doStateTests(Thread::new);
    doStateTests(ExtThread::new);

    doAllThreadsTests();

    doTLSTests();

    doTestEvents();
  }

  private static final class ExtThread extends Thread {
    public ExtThread(Runnable r) { super(r); }
  }

  private static class Holder {
    volatile boolean flag = false;
  }

  private static void doCurrentThreadStateTests() throws Exception {
    System.out.println(Integer.toHexString(getThreadState(null)));
    System.out.println(Integer.toHexString(getThreadState(Thread.currentThread())));
  }

  private static void doStateTests(Function<Runnable, Thread> mkThread) throws Exception {
    final CountDownLatch cdl1 = new CountDownLatch(1);
    final CountDownLatch cdl2 = new CountDownLatch(1);
    final CountDownLatch cdl3_1 = new CountDownLatch(1);
    final CountDownLatch cdl3_2 = new CountDownLatch(1);
    final CountDownLatch cdl4 = new CountDownLatch(1);
    final CountDownLatch cdl5 = new CountDownLatch(1);
    final Holder h = new Holder();
    final long ALMOST_INFINITE = 100000000;  // 1.1 days!
    final NativeWaiter w = new NativeWaiter();
    Runnable r = new Runnable() {
      @Override
      public void run() {
        try {
          cdl1.countDown();
          synchronized(cdl1) {
            cdl1.wait();
          }

          cdl2.countDown();
          synchronized(cdl2) {
            cdl2.wait(ALMOST_INFINITE);
          }

          cdl3_1.await();
          cdl3_2.countDown();
          synchronized(cdl3_2) {
            // Nothing, just wanted to block on cdl3.
          }

          cdl4.countDown();
          try {
            Thread.sleep(ALMOST_INFINITE);
          } catch (InterruptedException e) { }

          cdl5.countDown();
          while (!h.flag) {
            // Busy-loop.
          }

          nativeLoop(w.struct);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    };

    Thread t = mkThread.apply(r);
    System.out.println("Thread type is " + t.getClass());
    printThreadState(t);
    t.start();

    // Waiting.
    cdl1.await();
    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
    // up and continue
    final int WAITING_INDEF = 0x191;
    waitForState(t, WAITING_INDEF);
    synchronized(cdl1) {
      cdl1.notifyAll();
    }

    // Timed waiting.
    cdl2.await();
    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
    // up and continue
    final int WAITING_TIMED = 0x1a1;
    waitForState(t, WAITING_TIMED);
    synchronized(cdl2) {
      cdl2.notifyAll();
    }

    // Blocked on monitor.
    synchronized(cdl3_2) {
      cdl3_1.countDown();
      cdl3_2.await();
      // While the latch improves the chances to make good progress, scheduling might still be
      // messy. Wait till we get the right Java-side Thread state.
      do {
        Thread.yield();
      } while (t.getState() != Thread.State.BLOCKED);
      // Since internal thread suspension (For GC or other cases) can happen at any time and changes
      // the thread state we just have it print the majority thread state across 11 calls over 55
      // milliseconds.
      printMajorityThreadState(t, 11, 5);
    }

    // Sleeping.
    cdl4.await();
    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
    // up and continue
    final int WAITING_SLEEP = 0xe1;
    waitForState(t, WAITING_SLEEP);
    t.interrupt();

    // Running.
    cdl5.await();
    Thread.yield();
    Thread.sleep(1000);
    printThreadState(t);
    h.flag = true;

    // Native
    w.waitForNative();
    printThreadState(t);
    w.finish();

    // Dying.
    t.join();
    Thread.yield();
    Thread.sleep(1000);

    printThreadState(t);
  }

  private static void waitForState(Thread t, int desired) throws Exception {
    Thread.yield();
    Thread.sleep(1000);
    // This is super inconsistent so just wait for the desired state for up to 5 minutes then give
    // up and continue
    int state;
    Instant deadline = Instant.now().plusSeconds(60 * 5);
    while ((state = getThreadState(t)) != desired && deadline.isAfter(Instant.now())) {
      Thread.yield();
      Thread.sleep(100);
      Thread.yield();
    }
    printThreadState(state);
  }

  private static void doAllThreadsTests() {
    Thread[] threads = getAllThreads();
    List<Thread> threadList = new ArrayList<>(Arrays.asList(threads));

    // Filter out JIT thread. It may or may not be there depending on configuration.
    Iterator<Thread> it = threadList.iterator();
    while (it.hasNext()) {
      Thread t = it.next();
      if (t.getName().startsWith("Jit thread pool worker")) {
        it.remove();
        break;
      }
    }

    Collections.sort(threadList, THREAD_COMP);

    List<Thread> expectedList = new ArrayList<>();
    Set<Thread> threadsFromTraces = Thread.getAllStackTraces().keySet();

    expectedList.add(findThreadByName(threadsFromTraces, "FinalizerDaemon"));
    expectedList.add(findThreadByName(threadsFromTraces, "FinalizerWatchdogDaemon"));
    expectedList.add(findThreadByName(threadsFromTraces, "HeapTaskDaemon"));
    expectedList.add(findThreadByName(threadsFromTraces, "ReferenceQueueDaemon"));
    // We can't get the signal catcher through getAllStackTraces. So ignore it.
    // expectedList.add(findThreadByName(threadsFromTraces, "Signal Catcher"));
    expectedList.add(findThreadByName(threadsFromTraces, "TestThread"));
    expectedList.add(findThreadByName(threadsFromTraces, "main"));

    if (!threadList.containsAll(expectedList)) {
      throw new RuntimeException("Expected " + expectedList + " as subset, got " + threadList);
    }
    System.out.println(expectedList);
  }

  private static Thread findThreadByName(Set<Thread> threads, String name) {
    for (Thread t : threads) {
        if (t.getName().equals(name)) {
            return t;
        }
    }
    throw new RuntimeException("Did not find thread " + name + ": " + threads);
  }

  private static void doTLSTests() throws Exception {
    doTLSNonLiveTests();
    doTLSLiveTests();
  }

  private static void doTLSNonLiveTests() throws Exception {
    Thread t = new Thread();
    try {
      setTLS(t, 1);
      System.out.println("Expected failure setting TLS for non-live thread");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
    t.start();
    t.join();
    try {
      setTLS(t, 1);
      System.out.println("Expected failure setting TLS for non-live thread");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }

  private static void doTLSLiveTests() throws Exception {
    setTLS(Thread.currentThread(), 1);

    long l = getTLS(Thread.currentThread());
    if (l != 1) {
      throw new RuntimeException("Unexpected TLS value: " + l);
    };

    final CountDownLatch cdl1 = new CountDownLatch(1);
    final CountDownLatch cdl2 = new CountDownLatch(1);

    Runnable r = new Runnable() {
      @Override
      public void run() {
        try {
          cdl1.countDown();
          cdl2.await();
          setTLS(Thread.currentThread(), 2);
          if (getTLS(Thread.currentThread()) != 2) {
            throw new RuntimeException("Different thread issue");
          }
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    };

    Thread t = new Thread(r);
    t.start();
    cdl1.await();
    setTLS(Thread.currentThread(), 1);
    cdl2.countDown();

    t.join();
    if (getTLS(Thread.currentThread()) != 1) {
      throw new RuntimeException("Got clobbered");
    }
  }

  private static List<String> filterForThread(Object[] thread_messages, String thread_name) {
    List<String> messageListForThread = new ArrayList<String>();

    for (int i = 0; i < thread_messages.length; i++) {
      String message = (String)thread_messages[i];
      if (message.startsWith("Thread(" + thread_name + ")")) {
        messageListForThread.add(message);
      }
    }

    return messageListForThread;
  }

  private static void doTestEvents() throws Exception {
    enableThreadEvents(true);

    final CountDownLatch cdl1 = new CountDownLatch(1);
    final CountDownLatch cdl2 = new CountDownLatch(1);

    Runnable r = new Runnable() {
      @Override
      public void run() {
        try {
          cdl1.countDown();
          cdl2.await();
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    };
    String thread_name = "EventTestThread";
    Thread t = new Thread(r, thread_name);

    System.out.println("Constructed thread");
    Thread.yield();
    Thread.sleep(100);

    // Check that there are no events related to EventTestThread that we just created.
    System.out.println(filterForThread(getThreadEventMessages(), thread_name).toString());

    t.start();
    cdl1.await();

    System.out.println(filterForThread(getThreadEventMessages(), thread_name).toString());

    cdl2.countDown();
    t.join();
    System.out.println(filterForThread(getThreadEventMessages(), thread_name).toString());

    System.out.println("Thread joined");

    enableThreadEvents(false);
  }

  private final static Comparator<Thread> THREAD_COMP = new Comparator<Thread>() {
    public int compare(Thread o1, Thread o2) {
      return o1.getName().compareTo(o2.getName());
    }
  };

  private final static Map<Integer, String> STATE_NAMES = new HashMap<Integer, String>();
  private final static List<Integer> STATE_KEYS = new ArrayList<Integer>();
  static {
    STATE_NAMES.put(0x1, "ALIVE");
    STATE_NAMES.put(0x2, "TERMINATED");
    STATE_NAMES.put(0x4, "RUNNABLE");
    STATE_NAMES.put(0x400, "BLOCKED_ON_MONITOR_ENTER");
    STATE_NAMES.put(0x80, "WAITING");
    STATE_NAMES.put(0x10, "WAITING_INDEFINITELY");
    STATE_NAMES.put(0x20, "WAITING_WITH_TIMEOUT");
    STATE_NAMES.put(0x40, "SLEEPING");
    STATE_NAMES.put(0x100, "IN_OBJECT_WAIT");
    STATE_NAMES.put(0x200, "PARKED");
    STATE_NAMES.put(0x100000, "SUSPENDED");
    STATE_NAMES.put(0x200000, "INTERRUPTED");
    STATE_NAMES.put(0x400000, "IN_NATIVE");
    STATE_KEYS.addAll(STATE_NAMES.keySet());
    Collections.sort(STATE_KEYS);
  }

  // Call getThreadState 'votes' times waiting 'wait' millis between calls and print the most common
  // result.
  private static void printMajorityThreadState(Thread t, int votes, int wait) throws Exception {
    Map<Integer, Integer> states = new HashMap<>();
    for (int i = 0; i < votes; i++) {
      int cur_state = getThreadState(t);
      states.put(cur_state, states.getOrDefault(cur_state, 0) + 1);
      Thread.sleep(wait);  // Wait a little bit.
    }
    int best_state = -1;
    int highest_count = 0;
    for (Map.Entry<Integer, Integer> e : states.entrySet()) {
      if (e.getValue() > highest_count) {
        highest_count = e.getValue();
        best_state = e.getKey();
      }
    }
    printThreadState(best_state);
  }

  private static void printThreadState(Thread t) {
    printThreadState(getThreadState(t));
  }

  private static void printThreadState(int state) {
    StringBuilder sb = new StringBuilder();

    for (Integer i : STATE_KEYS) {
      if ((state & i) != 0) {
        if (sb.length()>0) {
          sb.append('|');
        }
        sb.append(STATE_NAMES.get(i));
      }
    }

    if (sb.length() == 0) {
      sb.append("NEW");
    }

    System.out.println(Integer.toHexString(state) + " = " + sb.toString());
  }

  private static void printThreadInfo(Thread t) {
    Object[] threadInfo = getThreadInfo(t);
    if (threadInfo == null || threadInfo.length != 5) {
      System.out.println(Arrays.toString(threadInfo));
      throw new RuntimeException("threadInfo length wrong");
    }

    System.out.println(threadInfo[0]);  // Name
    System.out.println(threadInfo[1]);  // Priority
    System.out.println(threadInfo[2]);  // Daemon
    System.out.println(threadInfo[3]);  // Threadgroup
    System.out.println(threadInfo[4] == null ? "null" : threadInfo[4].getClass());  // Context CL.
  }

  public static final class NativeWaiter {
    public long struct;
    public NativeWaiter() {
      struct = nativeWaiterStructAlloc();
    }
    public void waitForNative() {
      if (struct == 0l) {
        throw new Error("Already resumed from native!");
      }
      nativeWaiterStructWaitForNative(struct);
    }
    public void finish() {
      if (struct == 0l) {
        throw new Error("Already resumed from native!");
      }
      nativeWaiterStructFinish(struct);
      struct = 0;
    }
  }

  private static native long nativeWaiterStructAlloc();
  private static native void nativeWaiterStructWaitForNative(long struct);
  private static native void nativeWaiterStructFinish(long struct);
  private static native void nativeLoop(long w);

  private static native Thread getCurrentThread();
  private static native Object[] getThreadInfo(Thread t);
  private static native int getThreadState(Thread t);
  private static native Thread[] getAllThreads();
  private static native void setTLS(Thread t, long l);
  private static native long getTLS(Thread t);
  private static native void enableThreadEvents(boolean b);
  private static native String[] getThreadEventMessages();
}
