/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @test
 * @bug     4967283
 * @summary Basic unit test of thread states returned by
 *          ThreadMXBean.getThreadInfo.getThreadState().
 *          It also tests lock information returned by ThreadInfo.
 *
 * @author  Mandy Chung
 *
 * @build ThreadExecutionSynchronizer
 * @run main ThreadStateTest
 */

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.lang.management.ThreadInfo;

import java.util.concurrent.locks.LockSupport;

public class ThreadStateTest {
    private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean();
    private static boolean testFailed = false;

    static class Lock {
        private String name;
        Lock(String name) {
            this.name = name;
        }
        public String toString() {
            return name;
        }
    }
    private static Lock globalLock = new Lock("my lock");

    public static void main(String[] argv) {
        // Force thread state initialization now before the test
        // verification begins.
        Thread.currentThread().getState();

        MyThread myThread = new MyThread("MyThread");

        // before myThread starts
        // checkThreadState(myThread, Thread.State.NEW);

        myThread.start();
        myThread.waitUntilStarted();
        checkThreadState(myThread, Thread.State.RUNNABLE);
        checkLockInfo(myThread, Thread.State.RUNNABLE, null, null);

        myThread.suspend();
        goSleep(10);
        checkSuspendedThreadState(myThread, Thread.State.RUNNABLE);
        myThread.resume();

        synchronized (globalLock) {
            myThread.goBlocked();
            checkThreadState(myThread, Thread.State.BLOCKED);
            checkLockInfo(myThread, Thread.State.BLOCKED,
                          globalLock, Thread.currentThread());
        }

        myThread.goWaiting();
        checkThreadState(myThread, Thread.State.WAITING);
        checkLockInfo(myThread, Thread.State.WAITING,
                      globalLock, null);

        myThread.goTimedWaiting();
        checkThreadState(myThread, Thread.State.TIMED_WAITING);
        checkLockInfo(myThread, Thread.State.TIMED_WAITING,
                      globalLock, null);



      /*
       *********** parkUntil seems not working
       * ignore this park case for now.

         Bug ID : 5062095
       ***********************************************
        myThread.goParked();
        checkThreadState(myThread, Thread.State.WAITING);
        checkLockInfo(myThread, Thread.State.WAITING, null, null);

        myThread.goTimedParked();
        checkThreadState(myThread, Thread.State.TIMED_WAITING);
        checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null);

       */

        myThread.goSleeping();
        checkThreadState(myThread, Thread.State.TIMED_WAITING);
        checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null);


        myThread.terminate();
        // checkThreadState(myThread, ThreadState.TERMINATED);

        try {
            myThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("Unexpected exception.");
            testFailed = true;
        }
        if (testFailed)
            throw new RuntimeException("TEST FAILED.");
        System.out.println("Test passed.");
    }

    private static void checkSuspendedThreadState(Thread t, Thread.State state) {
        ThreadInfo info = tm.getThreadInfo(t.getId());
        if (info == null) {
            throw new RuntimeException(t.getName() +
               " expected to have ThreadInfo " +
               " but got null.");
        }

        if (info.getThreadState() != state) {
            throw new RuntimeException(t.getName() + " expected to be in " +
                state + " state but got " + info.getThreadState());
        }

        if (!info.isSuspended()) {
            throw new RuntimeException(t.getName() + " expected to be suspended " +
                " but isSuspended() returns " + info.isSuspended());
        }
        checkThreadState(t, state);
    }

    private static void checkThreadState(Thread t, Thread.State expected) {
        ThreadInfo ti = tm.getThreadInfo(t.getId());
        Thread.State state = ti.getThreadState();
        if (state == null) {
            throw new RuntimeException(t.getName() + " expected to have " +
                expected + " but got null.");
        }

        if (state != expected) {
            if (expected ==  Thread.State.BLOCKED) {
                int retryCount=0;
                while (ti.getThreadState() != expected) {
                    if (retryCount >= 500) {
                        throw new RuntimeException(t.getName() +
                            " expected to have " + expected + " but got " + state);
                     }
                     goSleep(100);
                }
            } else {
                throw new RuntimeException(t.getName() + " expected to have " +
                    expected + " but got " + state);
            }
        }
    }

    private static String getLockName(Object lock) {
        if (lock == null) return null;

        return lock.getClass().getName() + '@' +
            Integer.toHexString(System.identityHashCode(lock));
    }

    private static void checkLockInfo(Thread t, Thread.State state, Object lock, Thread owner) {
        ThreadInfo info = tm.getThreadInfo(t.getId());
        if (info == null) {
            throw new RuntimeException(t.getName() +
               " expected to have ThreadInfo " +
               " but got null.");
        }

        if (info.getThreadState() != state) {
            throw new RuntimeException(t.getName() + " expected to be in " +
                state + " state but got " + info.getThreadState());
        }

        if (lock == null && info.getLockName() != null) {
            throw new RuntimeException(t.getName() +
                " expected not to be blocked on any lock" +
                " but got " + info.getLockName());
        }
        String expectedLockName = getLockName(lock);
        if (lock != null && info.getLockName() == null) {
            throw new RuntimeException(t.getName() +
                " expected to be blocked on lock [" + expectedLockName +
                "] but got null.");
        }

        if (lock != null && !expectedLockName.equals(info.getLockName())) {
            throw new RuntimeException(t.getName() +
                " expected to be blocked on lock [" + expectedLockName +
                "] but got [" + info.getLockName() + "].");
        }

        if (owner == null && info.getLockOwnerName() != null) {
            throw new RuntimeException("Lock owner is expected " +
                " to be null but got " + info.getLockOwnerName());
        }

        if (owner != null && info.getLockOwnerName() == null) {
            throw new RuntimeException("Lock owner is expected to be " +
                owner.getName() +
                " but got null.");
        }
        if (owner != null && !info.getLockOwnerName().equals(owner.getName())) {
            throw new RuntimeException("Lock owner is expected to be " +
                owner.getName() +
                " but got " + owner.getName());
        }
        if (owner == null && info.getLockOwnerId() != -1) {
            throw new RuntimeException("Lock owner is expected " +
                " to be -1 but got " + info.getLockOwnerId());
        }

        if (owner != null && info.getLockOwnerId() <= 0) {
            throw new RuntimeException("Lock owner is expected to be " +
                owner.getName() + "(id = " + owner.getId() +
                ") but got " + info.getLockOwnerId());
        }
        if (owner != null && info.getLockOwnerId() != owner.getId()) {
            throw new RuntimeException("Lock owner is expected to be " +
                owner.getName() + "(id = " + owner.getId() +
                ") but got " + info.getLockOwnerId());
        }
        if (info.isSuspended()) {
            throw new RuntimeException(t.getName() +
                " isSuspended() returns " + info.isSuspended());
        }
    }

    private static void goSleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("Unexpected exception.");
            testFailed = true;
        }
    }

    static class MyThread extends Thread {
        private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer();

        MyThread(String name) {
            super(name);
        }

        private final int RUNNABLE = 0;
        private final int BLOCKED = 1;
        private final int WAITING = 2;
        private final int TIMED_WAITING = 3;
        private final int PARKED = 4;
        private final int TIMED_PARKED = 5;
        private final int SLEEPING = 6;
        private final int TERMINATE = 7;
        private int state = RUNNABLE;

        private boolean done = false;
        public void run() {
            // Signal main thread to continue.
            thrsync.signal();
            while (!done) {
                switch (state) {
                    case RUNNABLE: {
                        double sum = 0;
                        for (int i = 0; i < 1000; i++) {
                           double r = Math.random();
                           double x = Math.pow(3, r);
                           sum += x - r;
                        }
                        break;
                    }
                    case BLOCKED: {
                        // signal main thread.
                        thrsync.signal();
                        System.out.println("  myThread is going to block.");
                        synchronized (globalLock) {
                            // finish blocking
                            state = RUNNABLE;
                        }
                        break;
                    }
                    case WAITING: {
                        synchronized (globalLock) {
                            // signal main thread.
                            thrsync.signal();
                            System.out.println("  myThread is going to wait.");
                            try {
                                globalLock.wait();
                            } catch (InterruptedException e) {
                                // ignore
                            }
                        }
                        break;
                    }
                    case TIMED_WAITING: {
                        synchronized (globalLock) {
                            // signal main thread.
                            thrsync.signal();
                            System.out.println("  myThread is going to timed wait.");
                            try {
                                globalLock.wait(10000);
                            } catch (InterruptedException e) {
                                // ignore
                            }
                        }
                        break;
                    }
                    case PARKED: {
                        // signal main thread.
                        thrsync.signal();
                        System.out.println("  myThread is going to park.");
                        LockSupport.park();
                        // give a chance for the main thread to block
                        System.out.println("  myThread is going to park.");
                        goSleep(10);
                        break;
                    }
                    case TIMED_PARKED: {
                        // signal main thread.
                        thrsync.signal();
                        System.out.println("  myThread is going to timed park.");
                        long deadline = System.currentTimeMillis() + 10000*1000;
                        LockSupport.parkUntil(deadline);

                        // give a chance for the main thread to block
                        goSleep(10);
                        break;
                    }
                    case SLEEPING: {
                        // signal main thread.
                        thrsync.signal();
                        System.out.println("  myThread is going to sleep.");
                        try {
                            Thread.sleep(1000000);
                        } catch (InterruptedException e) {
                            // finish sleeping
                            interrupted();
                        }
                        break;
                    }
                    case TERMINATE: {
                        done = true;
                        // signal main thread.
                        thrsync.signal();
                        break;
                    }
                    default:
                        break;
                }
            }
        }
        public void waitUntilStarted() {
            // wait for MyThread.
            thrsync.waitForSignal();
            goSleep(10);
        }

        public void goBlocked() {
            System.out.println("Waiting myThread to go blocked.");
            setState(BLOCKED);
            // wait for MyThread to get blocked
            thrsync.waitForSignal();
            goSleep(20);
        }

        public void goWaiting() {
            System.out.println("Waiting myThread to go waiting.");
            setState(WAITING);
            // wait for  MyThread to wait on object.
            thrsync.waitForSignal();
            goSleep(20);
        }
        public void goTimedWaiting() {
            System.out.println("Waiting myThread to go timed waiting.");
            setState(TIMED_WAITING);
            // wait for MyThread timed wait call.
            thrsync.waitForSignal();
            goSleep(20);
        }
        public void goParked() {
            System.out.println("Waiting myThread to go parked.");
            setState(PARKED);
            // wait for  MyThread state change to PARKED.
            thrsync.waitForSignal();
            goSleep(20);
        }
        public void goTimedParked() {
            System.out.println("Waiting myThread to go timed parked.");
            setState(TIMED_PARKED);
            // wait for  MyThread.
            thrsync.waitForSignal();
            goSleep(20);
        }

        public void goSleeping() {
            System.out.println("Waiting myThread to go sleeping.");
            setState(SLEEPING);
            // wait for  MyThread.
            thrsync.waitForSignal();
            goSleep(20);
        }
        public void terminate() {
            System.out.println("Waiting myThread to terminate.");
            setState(TERMINATE);
            // wait for  MyThread.
            thrsync.waitForSignal();
            goSleep(20);
        }

        private void setState(int newState) {
            switch (state) {
                case BLOCKED:
                    while (state == BLOCKED) {
                        goSleep(20);
                    }
                    state = newState;
                    break;
                case WAITING:
                case TIMED_WAITING:
                    state = newState;
                    synchronized (globalLock) {
                        globalLock.notify();
                    }
                    break;
                case PARKED:
                case TIMED_PARKED:
                    state = newState;
                    LockSupport.unpark(this);
                    break;
                case SLEEPING:
                    state = newState;
                    this.interrupt();
                    break;
                default:
                    state = newState;
                    break;
            }
        }
    }
}
