/* * 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; } } 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 launchFiveSecondDummyThread() { 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(10000); } catch(InterruptedException ie) { wasInterrupted = true; } } }; st.start(); try { Thread.sleep(5000); } catch(InterruptedException e) { fail("Unexpected InterruptedException was thrown"); } st.interrupt(); try { Thread.sleep(5000); } 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(10000, 99999); } catch(InterruptedException ie) { wasInterrupted = true; } } }; st.start(); try { Thread.sleep(5000, 99999); } catch(InterruptedException e) { fail("Unexpected InterruptedException was thrown"); } st.interrupt(); try { Thread.sleep(5000); } 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(11000); } 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 < 10000; 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 = launchFiveSecondDummyThread(); 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 = launchFiveSecondDummyThread(); 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) { } } }