/*
 *  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 libcore.java.lang;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.LockSupport;
import libcore.java.lang.ref.FinalizationTester;

public class OldThreadTest extends junit.framework.TestCase {

    static class SimpleThread implements Runnable {
        int delay;

        public void run() {
            try {
                synchronized (this) {
                    this.notify();
                    this.wait(delay);
                }
            } catch (InterruptedException e) {
                return;
            }

        }

        public SimpleThread(int d) {
            if (d >= 0)
                delay = d;
        }
    }

    @SuppressWarnings("DeadThread")
    public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_RunnableLjava_lang_StringL$L() {
        ThreadGroup tg = new ThreadGroup("Test Group2");
        st = new Thread(tg, new SimpleThread(1), "SimpleThread3", 1);
        assertTrue("Constructed incorrect thread", (st.getThreadGroup() == tg)
                && st.getName().equals("SimpleThread3"));
        st.start();
        try {
            st.join();
        } catch (InterruptedException e) {
        }
        tg.destroy();

        try {
            new Thread(tg, new SimpleThread(1), "SimpleThread3",
                    Integer.MAX_VALUE);
            fail("StackOverflowError/OutOfMemoryError is not thrown.");
        } catch(IllegalThreadStateException itse) {
            //expected
        }

    }

    public void test_dumpStack() {
        try {
            PrintStream savedErr = System.err;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            System.setErr(new PrintStream(baos));
            Thread.dumpStack();
            System.setErr(savedErr);

            String s = new String(baos.toByteArray());

            assertTrue(s.contains("java.lang.Thread.dumpStack"));

        } catch(Exception e) {
            fail("Unexpected exception was thrown: " + e.toString());
        }
    }

    class MonitoredClass {
        public synchronized void enterLocked() {
            boolean b = Thread.holdsLock(this);
            assertTrue("Thread should hold lock for object", b);
        }

        public void enterNonLocked() {
            boolean b = Thread.holdsLock(this);
            assertFalse("Thread should not hold lock for object", b);
        }

    }

    boolean wasInterrupted = false;

    public void test_joinWithSpuriousInterruption() throws InterruptedException {
        final Thread parker = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    // we used to get spurious wakeups upon unparking
                    LockSupport.park();
                }
            }
        };
        Thread unparker = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(100);
                        LockSupport.unpark(parker);
                    } catch (InterruptedException expected) {
                    }
                }
            }
        };

        long startNanos = System.nanoTime();
        parker.start();
        unparker.start();
        parker.join(500, 500000);
        long netWaitTime = System.nanoTime() - startNanos;
        assertTrue("Expected to wait at least 500000000ns, but was " + netWaitTime + "ns",
                netWaitTime > 500000000);
    }

    public void test_setContextClassLoader() {
        ClassLoader pcl = new ClassLoader() {};
        st = new Thread();
        st.setContextClassLoader(pcl);
        assertEquals(pcl, st.getContextClassLoader());

        st.setContextClassLoader(null);
        assertNull(st.getContextClassLoader());
    }

    public void test_setDaemonZ() {
        st = new Thread(new SimpleThread(5));
        st.start();
        try {
            st.setDaemon(false);
            fail("setDaemon() must throw exception for started thread");
        } catch (IllegalThreadStateException ex) {
            // We expect this one.
        }
    }

    private Thread launchFiveSecondFakeThread() {
        Thread thread = new Thread() {
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // Ignore
                }
            }
        };

        thread.start();

        return thread;
    }

    /**
     * java.lang.Thread#sleep(long)
     */
    public void test_sleepJ() {
        // Note: Not too much we can test here that can be reliably measured.

        // Check that basic behavior is about right (with some tolerance)
        long stime = System.currentTimeMillis();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            fail("Unexpected InterruptedException was thrown");
        }

        long ftime = System.currentTimeMillis();

        assertTrue("Failed to sleep long enough", (ftime - stime) >= 500);
        assertTrue("Failed to wake up early enough", (ftime - stime) <= 1500);

        // Check that interrupt works
        st = new Thread() {
            public void run() {
                try {
                    sleep(1000);
                } catch(InterruptedException ie) {
                    wasInterrupted = true;
                }
            }
        };

        st.start();

        try {
            Thread.sleep(500);
        } catch(InterruptedException e) {
            fail("Unexpected InterruptedException was thrown");
        }

        st.interrupt();

        try {
            Thread.sleep(500);
        } catch(InterruptedException e) {
            fail("Unexpected InterruptedException was thrown");
        }

        assertTrue(wasInterrupted);
    }

    public void test_sleepJI() {
        // Note: Not too much we can test here that can be reliably measured.

        // Check that basic behavior is about right (with some tolerance)
        long stime = System.currentTimeMillis();

        try {
            Thread.sleep(1000, 99999);
        } catch (InterruptedException e) {
            fail("Unexpected InterruptedException was thrown");
        }

        long ftime = System.currentTimeMillis();

        assertTrue("Failed to sleep long enough", (ftime - stime) >= 500);
        assertTrue("Failed to wake up early enough", (ftime - stime) <= 1500);

        // Check that interrupt works
        st = new Thread() {
            public void run() {
                try {
                    sleep(1000, 9999);
                } catch(InterruptedException ie) {
                    wasInterrupted = true;
                }
            }
        };

        st.start();

        try {
            Thread.sleep(500, 9999);
        } catch(InterruptedException e) {
            fail("Unexpected InterruptedException was thrown");
        }

        st.interrupt();

        try {
            Thread.sleep(500);
        } catch(InterruptedException e) {
            fail("Unexpected InterruptedException was thrown");
        }

        assertTrue(wasInterrupted);
    }

    public void test_yield() {

        Counter [] countersNotYeld = new Counter[10];

        for(int i = 0; i < 10; i++) {
            countersNotYeld[i] = new Counter(false);
        }
        Counter countersYeld = new Counter(true);
        try {
            Thread.sleep(1100);
        } catch(InterruptedException ie) {}

        for(Counter c:countersNotYeld) {
            assertTrue(countersYeld.counter == c.counter);
        }
    }

    class Counter extends Thread {
        public int counter = 0;
        boolean isDoYield = false;

        public Counter(boolean isDoYield) {
            this.isDoYield = isDoYield;
            start();
        }

        public void run() {
            for(int i = 0; i < 1000; i++) {
                if(isDoYield)
                    yield();
                counter ++;
            }
        }
    }


    public void test_getState() throws InterruptedException {
        Thread.State state = Thread.currentThread().getState();
        assertNotNull(state);
        assertEquals(Thread.State.RUNNABLE, state);

        run = true;
        final Semaphore sem = new Semaphore(0);
        final Object lock = new Object();
        Thread th = new Thread() {
            @Override
            public void run() {
                  while (!sem.hasQueuedThreads()) {}
                  sem.release();

                  // RUNNABLE
                  while (run) {}

                  try {
                      // WAITING
                      sem.acquire();
                  } catch (InterruptedException e) {
                      fail("InterruptedException was thrown.");
                  }

                  // BLOCKED
                  synchronized (lock) {
                      lock.equals(new Object());
                  }
                  synchronized (lock) {
                      try {
                        sem.release();

                        // TIMED_WAITING
                        lock.wait(Long.MAX_VALUE);
                      } catch (InterruptedException e) {
                          // expected
                      }
                  }

                  // TERMINATED upon return
            }
        };
        assertEquals(Thread.State.NEW, th.getState());
        th.start();
        sem.acquire();
        assertEquals(Thread.State.RUNNABLE, th.getState());
        run = false;

        Thread.sleep(200);

        assertEquals(Thread.State.WAITING, th.getState());
        synchronized (lock) {
            sem.release();
            long start = System.currentTimeMillis();
            while(start + 1000 > System.currentTimeMillis()) {}
            assertEquals(Thread.State.BLOCKED, th.getState());
        }

        sem.acquire();

        synchronized (lock) {
            assertEquals(Thread.State.TIMED_WAITING, th.getState());
            th.interrupt();
        }

        th.join(1000);
        assertEquals(Thread.State.TERMINATED, th.getState());
    }
    volatile boolean run;

    public void test_holdsLock() {
        MonitoredClass monitor = new MonitoredClass();

        monitor.enterLocked();
        monitor.enterNonLocked();

        try {
            Thread.holdsLock(null);
            fail("NullPointerException was not thrown.");
        } catch(NullPointerException npe) {
            //expected
        }
    }

    @SuppressWarnings("deprecation")
    public void test_stop() {
        Thread thread = launchFiveSecondFakeThread();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // Ignore
        }

        try {
            thread.stop();
            fail();
        } catch (UnsupportedOperationException expected) {
        }
    }

    public void test_start() {
        Thread thr = new Thread();
        thr.start();
        try {
            thr.start();
        } catch(IllegalThreadStateException itse){
            //expected
        }
    }

    @SuppressWarnings("deprecation")
    public void test_stopLjava_lang_Throwable_subtest0() {
        Thread thread = new Thread() {
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // Ignore
                }
            }
        };

        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // Ignore
        }

        try {
            thread.stop(new Exception("Oops!"));
            fail();
        } catch (UnsupportedOperationException expected) {
        }
    }

    @SuppressWarnings("deprecation")
    public void test_suspend() {
        Thread thread = launchFiveSecondFakeThread();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // Ignore
        }

        try {
            thread.suspend();
            fail();
        } catch (UnsupportedOperationException expected) {
        }
    }

    Thread st, ct, spinner;

    @Override
    protected void tearDown() {
        try {
            if (st != null)
                st.interrupt();
        } catch (Exception e) {
        }
        try {
            if (spinner != null)
                spinner.interrupt();
        } catch (Exception e) {
        }
        try {
            if (ct != null)
                ct.interrupt();
        } catch (Exception e) {
        }

        try {
            spinner = null;
            st = null;
            ct = null;
            FinalizationTester.induceFinalization();
        } catch (Exception e) {
        }
    }
}
