/*
 * Copyright (C) 2007 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 libcore.java.lang;

import junit.framework.TestCase;

public class OldAndroidMonitorTest extends TestCase {

    public void testWaitArgumentsTest() throws Exception {
            /* Try some valid arguments.  These should all
             * return very quickly.
             */
            try {
                synchronized (this) {
                    /* millisecond version */
                    wait(1);
                    wait(10);

                    /* millisecond + nanosecond version */
                    wait(0, 1);
                    wait(0, 999999);
                    wait(1, 1);
                    wait(1, 999999);
                }
            } catch (InterruptedException ex) {
                throw new RuntimeException("good Object.wait() interrupted",
                        ex);
            } catch (Exception ex) {
                throw new RuntimeException("Unexpected exception when calling" +
                        "Object.wait() with good arguments", ex);
            }

            /* Try some invalid arguments.
             */
            boolean sawException = false;
            try {
                synchronized (this) {
                    wait(-1);
                }
            } catch (InterruptedException ex) {
                throw new RuntimeException("bad Object.wait() interrupted", ex);
            } catch (IllegalArgumentException ex) {
                sawException = true;
            } catch (Exception ex) {
                throw new RuntimeException("Unexpected exception when calling" +
                        "Object.wait() with bad arguments", ex);
            }
            if (!sawException) {
                throw new RuntimeException("bad call to Object.wait() should " +
                        "have thrown IllegalArgumentException");
            }

            sawException = false;
            try {
                synchronized (this) {
                    wait(0, -1);
                }
            } catch (InterruptedException ex) {
                throw new RuntimeException("bad Object.wait() interrupted", ex);
            } catch (IllegalArgumentException ex) {
                sawException = true;
            } catch (Exception ex) {
                throw new RuntimeException("Unexpected exception when calling" +
                        "Object.wait() with bad arguments", ex);
            }
            if (!sawException) {
                throw new RuntimeException("bad call to Object.wait() should " +
                        "have thrown IllegalArgumentException");
            }

            sawException = false;
            try {
                synchronized (this) {
                    /* The legal range of nanos is 0-999999. */
                    wait(0, 1000000);
                }
            } catch (InterruptedException ex) {
                throw new RuntimeException("bad Object.wait() interrupted", ex);
            } catch (IllegalArgumentException ex) {
                sawException = true;
            } catch (Exception ex) {
                throw new RuntimeException("Unexpected exception when calling" +
                        "Object.wait() with bad arguments", ex);
            }
            if (!sawException) {
                throw new RuntimeException("bad call to Object.wait() should " +
                        "have thrown IllegalArgumentException");
            }
    }

    private class Interrupter extends Thread {
            Waiter waiter;

            Interrupter(String name, Waiter waiter) {
                super(name);
                this.waiter = waiter;
            }

            public void run() {
                try {
                    run_inner();
                } catch (Throwable t) {
                    OldAndroidMonitorTest.errorException = t;
                    OldAndroidMonitorTest.testThread.interrupt();
                }
            }

            void run_inner() {
                waiter.spin = true;
                // System.out.println("InterruptTest: starting waiter");
                waiter.start();

                try {
                    Thread.currentThread().sleep(500);
                } catch (InterruptedException ex) {
                    throw new RuntimeException("Test sleep interrupted.", ex);
                }

                /* Waiter is spinning, and its monitor should still be thin.
                 */
                // System.out.println("Test interrupting waiter");
                waiter.interrupt();
                waiter.spin = false;

                for (int i = 0; i < 3; i++) {
                    /* Wait for the waiter to start waiting.
                     */
                    synchronized (waiter.interrupterLock) {
                        try {
                            waiter.interrupterLock.wait();
                        } catch (InterruptedException ex) {
                            throw new RuntimeException("Test wait interrupted.", ex);
                        }
                    }

                    /* Before interrupting, grab the waiter lock, which
                     * guarantees that the waiter is already sitting in wait().
                     */
                    synchronized (waiter) {
                        //System.out.println("Test interrupting waiter (" + i + ")");
                        waiter.interrupt();
                    }
                }

                // System.out.println("Test waiting for waiter to die.");
                try {
                    waiter.join();
                } catch (InterruptedException ex) {
                    throw new RuntimeException("Test join interrupted.", ex);
                }
                // System.out.println("InterruptTest done.");
            }
        }

    private class Waiter extends Thread {
            Object interrupterLock = new Object();
            Boolean spin = false;

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

            public void run() {
                try {
                    run_inner();
                } catch (Throwable t) {
                    OldAndroidMonitorTest.errorException = t;
                    OldAndroidMonitorTest.testThread.interrupt();
                }
            }

            void run_inner() {
                // System.out.println("Waiter spinning");
                while (spin) {
                    // We're going to get interrupted while we spin.
                }
                if (interrupted()) {
                    // System.out.println("Waiter done spinning; interrupted.");
                } else {
                    throw new RuntimeException("Thread not interrupted " +
                                               "during spin");
                }

                synchronized (this) {
                    Boolean sawEx = false;

                    try {
                        synchronized (interrupterLock) {
                            interrupterLock.notify();
                        }
                        // System.out.println("Waiter calling wait()");
                        this.wait();
                    } catch (InterruptedException ex) {
                        sawEx = true;
                        // System.out.println("wait(): Waiter caught " + ex);
                    }
                    // System.out.println("wait() finished");

                    if (!sawEx) {
                        throw new RuntimeException("Thread not interrupted " +
                                                   "during wait()");
                    }
                }
                synchronized (this) {
                    Boolean sawEx = false;

                    try {
                        synchronized (interrupterLock) {
                            interrupterLock.notify();
                        }
                        // System.out.println("Waiter calling wait(1000)");
                        this.wait(1000);
                    } catch (InterruptedException ex) {
                        sawEx = true;
                        // System.out.println("wait(1000): Waiter caught " + ex);
                    }
                    // System.out.println("wait(1000) finished");

                    if (!sawEx) {
                        throw new RuntimeException("Thread not interrupted " +
                                                   "during wait(1000)");
                    }
                }
                synchronized (this) {
                    Boolean sawEx = false;

                    try {
                        synchronized (interrupterLock) {
                            interrupterLock.notify();
                        }
                        // System.out.println("Waiter calling wait(1000, 5000)");
                        this.wait(1000, 5000);
                    } catch (InterruptedException ex) {
                        sawEx = true;
                        // System.out.println("wait(1000, 5000): Waiter caught " + ex);
                    }
                    // System.out.println("wait(1000, 5000) finished");

                    if (!sawEx) {
                        throw new RuntimeException("Thread not interrupted " +
                                                   "during wait(1000, 5000)");
                    }
                }

               //  System.out.println("Waiter returning");
            }
        }

    private static Throwable errorException;
    private static Thread testThread;

    // TODO: Flaky test. Add back MediumTest annotation once fixed
    public void testInterruptTest() throws Exception {


            testThread = Thread.currentThread();
            errorException = null;

            Waiter waiter = new Waiter("InterruptTest Waiter");
            Interrupter interrupter =
                    new Interrupter("InterruptTest Interrupter", waiter);
            interrupter.start();

            try {
                interrupter.join();
                waiter.join();
            } catch (InterruptedException ex) {
                throw new RuntimeException("Test join interrupted.", ex);
            }

            if (errorException != null) {
                throw new RuntimeException("InterruptTest failed",
                                           errorException);
            }




    }

     private static void deepWait(int depth, Object lock) {
            synchronized (lock) {
                if (depth > 0) {
                    deepWait(depth - 1, lock);
                } else {
                    String threadName = Thread.currentThread().getName();
                    try {
                        // System.out.println(threadName + " waiting");
                        lock.wait();
                        // System.out.println(threadName + " done waiting");
                    } catch (InterruptedException ex) {
                        // System.out.println(threadName + " interrupted.");
                    }
                }
            }
        }

        private class Worker extends Thread {
            Object lock;
            int id;

            Worker(int id, Object lock) {
                super("Worker(" + id + ")");
                this.id = id;
                this.lock = lock;
            }

            public void run() {
                int iterations = 0;

                while (OldAndroidMonitorTest.running) {
                    OldAndroidMonitorTest.deepWait(id, lock);
                    iterations++;
                }
                // System.out.println(getName() + " done after " + iterations + " iterations.");
            }
        }

    private static Object commonLock = new Object();
        private static Boolean running = false;


    public void testNestedMonitors() throws Exception {
        final int NUM_WORKERS = 5;

            Worker w[] = new Worker[NUM_WORKERS];
            int i;

            for (i = 0; i < NUM_WORKERS; i++) {
                w[i] = new Worker(i * 2 - 1, new Object());
            }

            running = true;

            // System.out.println("NestedMonitors: starting workers");
            for (i = 0; i < NUM_WORKERS; i++) {
                w[i].start();
            }

            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException ex) {
               // System.out.println("Test sleep interrupted.");
            }

            for (i = 0; i < 100; i++) {
                for (int j = 0; j < NUM_WORKERS; j++) {
                    synchronized (w[j].lock) {
                        w[j].lock.notify();
                    }
                }
            }

            // System.out.println("NesterMonitors: stopping workers");
            running = false;
            for (i = 0; i < NUM_WORKERS; i++) {
                synchronized (w[i].lock) {
                    w[i].lock.notifyAll();
                }
            }
    }

    private static class CompareAndExchange extends Thread {
        static Object toggleLock = null;
        static int toggle = -1;
        static Boolean running = false;

        public void run() {
            toggleLock = new Object();
            toggle = -1;

            Worker w1 = new Worker(0, 1);
            Worker w2 = new Worker(2, 3);
            Worker w3 = new Worker(4, 5);
            Worker w4 = new Worker(6, 7);

            running = true;

            // System.out.println("CompareAndExchange: starting workers");

            w1.start();
            w2.start();
            w3.start();
            w4.start();

            try {
                this.sleep(10000);
            } catch (InterruptedException ex) {
                // System.out.println(getName() + " interrupted.");
            }

            // System.out.println("MonitorTest: stopping workers");
            running = false;

            toggleLock = null;
        }

        class Worker extends Thread {
            int i1;
            int i2;

            Worker(int i1, int i2) {
                super("Worker(" + i1 + ", " + i2 + ")");
                this.i1 = i1;
                this.i2 = i2;
            }

            public void run() {
                int iterations = 0;

                /* Latch this because run() may set the static field to
                 * null at some point.
                 */
                Object toggleLock = CompareAndExchange.toggleLock;

                // System.out.println(getName() + " running");
                try {
                    while (CompareAndExchange.running) {
                        synchronized (toggleLock) {
                            int test;
                            int check;

                            if (CompareAndExchange.toggle == i1) {
                                this.sleep(5 + i2);
                                CompareAndExchange.toggle = test = i2;
                            } else {
                                this.sleep(5 + i1);
                                CompareAndExchange.toggle = test = i1;
                            }
                            if ((check = CompareAndExchange.toggle) != test) {
//                                System.out.println("Worker(" + i1 + ", " +
//                                                   i2 + ") " + "test " + test +
//                                                   " != toggle " + check);
                                throw new RuntimeException(
                                        "locked value changed");
                            }
                        }

                        iterations++;
                    }
                } catch (InterruptedException ex) {
                   // System.out.println(getName() + " interrupted.");
                }

//                System.out.println(getName() + " done after " +
//                                   iterations + " iterations.");
            }
        }
    }
}
