blob: 47eb16688caa332695c88c342ba0fbbe24ad426b [file] [log] [blame]
/*
* 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 org.apache.harmony.luni.tests.java.lang;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.security.Permission;
import java.util.Map;
import java.util.concurrent.Semaphore;
import dalvik.annotation.AndroidOnly;
import dalvik.annotation.KnownFailure;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
@TestTargetClass(Thread.class)
public class ThreadTest extends junit.framework.TestCase {
int counter = 0;
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;
}
}
static class YieldThread implements Runnable {
volatile int delay;
public void run() {
int x = 0;
while (true) {
++x;
}
}
public YieldThread(int d) {
if (d >= 0)
delay = d;
}
}
static class ResSupThread implements Runnable {
Thread parent;
volatile int checkVal = -1;
public void run() {
try {
synchronized (this) {
this.notify();
}
while (true) {
checkVal++;
zz();
Thread.sleep(100);
}
} catch (InterruptedException e) {
return;
} catch (BogusException e) {
try {
// Give parent a chance to sleep
Thread.sleep(500);
} catch (InterruptedException x) {
}
parent.interrupt();
while (!Thread.currentThread().isInterrupted()) {
// Don't hog the CPU
try {
Thread.sleep(50);
} catch (InterruptedException x) {
// This is what we've been waiting for...don't throw it
// away!
break;
}
}
}
}
public void zz() throws BogusException {
}
public ResSupThread(Thread t) {
parent = t;
}
public synchronized int getCheckVal() {
return checkVal;
}
}
static class BogusException extends Throwable {
private static final long serialVersionUID = 1L;
public BogusException(String s) {
super(s);
}
}
// TODO android-added
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);
}
}
Thread st, ct, spinner;
static boolean calledMySecurityManager = false;
boolean wasInterrupted = false;
/**
* @tests java.lang.Thread#Thread()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {}
)
public void test_Constructor() {
// Test for method java.lang.Thread()
Thread t;
SecurityManager m = new SecurityManager() {
@Override
public ThreadGroup getThreadGroup() {
calledMySecurityManager = true;
return Thread.currentThread().getThreadGroup();
}
@Override
public void checkPermission(Permission permission) {
if (permission.getName().equals("setSecurityManager")) {
return;
}
super.checkPermission(permission);
}
};
try {
// To see if it checks Thread creation with our SecurityManager
System.setSecurityManager(m);
t = new Thread();
} finally {
// restore original, no side-effects
System.setSecurityManager(null);
}
assertTrue("Did not call SecurityManager.getThreadGroup ()",
calledMySecurityManager);
t.start();
}
/**
* @tests java.lang.Thread#Thread(java.lang.Runnable)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {java.lang.Runnable.class}
)
public void test_ConstructorLjava_lang_Runnable() {
// Test for method java.lang.Thread(java.lang.Runnable)
try {
ct = new Thread(new SimpleThread(10));
ct.start();
} catch (Exception e) {
fail("Failed to create subthread : " + e.getMessage());
}
}
/**
* @tests java.lang.Thread#Thread(java.lang.Runnable, java.lang.String)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {java.lang.Runnable.class, java.lang.String.class}
)
public void test_ConstructorLjava_lang_RunnableLjava_lang_String() {
// Test for method java.lang.Thread(java.lang.Runnable,
// java.lang.String)
Thread st1 = new Thread(new SimpleThread(1), "SimpleThread1");
assertEquals("Constructed thread with incorrect thread name", "SimpleThread1", st1
.getName());
st1.start();
}
/**
* @tests java.lang.Thread#Thread(java.lang.String)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {java.lang.String.class}
)
public void test_ConstructorLjava_lang_String() {
// Test for method java.lang.Thread(java.lang.String)
Thread t = new Thread("Testing");
assertEquals("Created tread with incorrect name",
"Testing", t.getName());
t.start();
}
/**
* @tests java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.Runnable)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {java.lang.ThreadGroup.class, java.lang.Runnable.class}
)
public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_Runnable() {
// Test for method java.lang.Thread(java.lang.ThreadGroup,
// java.lang.Runnable)
ThreadGroup tg = new ThreadGroup("Test Group1");
st = new Thread(tg, new SimpleThread(1), "SimpleThread2");
assertTrue("Returned incorrect thread group", st.getThreadGroup() == tg);
st.start();
try {
st.join();
} catch (InterruptedException e) {
}
tg.destroy();
}
/**
* @tests java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.Runnable,
* java.lang.String)lo
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {java.lang.ThreadGroup.class, java.lang.Runnable.class, java.lang.String.class}
)
public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_RunnableLjava_lang_String() {
// Test for method java.lang.Thread(java.lang.ThreadGroup,
// java.lang.Runnable, java.lang.String)
ThreadGroup tg = new ThreadGroup("Test Group2");
st = new Thread(tg, new SimpleThread(1), "SimpleThread3");
assertTrue("Constructed incorrect thread", (st.getThreadGroup() == tg)
&& st.getName().equals("SimpleThread3"));
st.start();
try {
st.join();
} catch (InterruptedException e) {
}
tg.destroy();
Runnable r = new Runnable() {
public void run() {
}
};
ThreadGroup foo = null;
try {
new Thread(foo = new ThreadGroup("foo"), r, null);
// Should not get here
fail("Null cannot be accepted as Thread name");
} catch (NullPointerException npe) {
assertTrue("Null cannot be accepted as Thread name", true);
foo.destroy();
}
}
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {java.lang.ThreadGroup.class, java.lang.Runnable.class, java.lang.String.class, long.class}
)
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();
Runnable r = new Runnable() {
public void run() {
}
};
try {
new Thread(tg, new SimpleThread(1), "SimpleThread3",
Integer.MAX_VALUE);
fail("StackOverflowError/OutOfMemoryError is not thrown.");
} catch(IllegalThreadStateException itse) {
//expected
}
}
/**
* @tests java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.String)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "Thread",
args = {java.lang.ThreadGroup.class, java.lang.String.class}
)
public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_String() {
// Test for method java.lang.Thread(java.lang.ThreadGroup,
// java.lang.String)
st = new Thread(new SimpleThread(1), "SimpleThread4");
assertEquals("Returned incorrect thread name",
"SimpleThread4", st.getName());
st.start();
}
/**
* @tests java.lang.Thread#activeCount()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "activeCount",
args = {}
)
public void test_activeCount() {
// Test for method int java.lang.Thread.activeCount()
Thread t = new Thread(new SimpleThread(1));
int active = Thread.activeCount();
assertTrue("Incorrect read made: " + active, active > 0);
t.start();
try {
t.join();
} catch (InterruptedException e) {
}
}
/**
* @tests java.lang.Thread#checkAccess()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "checkAccess",
args = {}
)
public void test_checkAccess() {
// Test for method void java.lang.Thread.checkAccess()
ThreadGroup tg = new ThreadGroup("Test Group3");
try {
st = new Thread(tg, new SimpleThread(1), "SimpleThread5");
st.checkAccess();
assertTrue("CheckAccess passed", true);
} catch (SecurityException e) {
fail("CheckAccess failed : " + e.getMessage());
}
st.start();
try {
st.join();
} catch (InterruptedException e) {
}
tg.destroy();
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.checkAccess();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#countStackFrames()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "countStackFrames",
args = {}
)
@SuppressWarnings("deprecation")
public void test_countStackFrames() {
/*
* Thread.countStackFrames() is unpredictable, so we just test that it
* doesn't throw an exception.
*/
try {
Thread.currentThread().countStackFrames();
} catch (Throwable t) {
fail("unexpected throwable: " + t.toString());
}
}
/**
* @tests java.lang.Thread#currentThread()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "currentThread",
args = {}
)
public void test_currentThread() {
assertNotNull(Thread.currentThread());
}
/**
* @tests java.lang.Thread#destroy()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "destroy",
args = {}
)
@SuppressWarnings("deprecation")
public void test_destroy() {
try {
new Thread().destroy();
// FIXME uncomment when IBM VME is updated
fail("NoSuchMethodError was not thrown");
} catch (NoSuchMethodError e) {
}
}
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "dumpStack",
args = {}
)
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());
}
}
/**
* @tests java.lang.Thread#enumerate(java.lang.Thread[])
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "enumerate",
args = {java.lang.Thread[].class}
)
public void test_enumerate$Ljava_lang_Thread() {
// Test for method int java.lang.Thread.enumerate(java.lang.Thread [])
// The test has been updated according to HARMONY-1974 JIRA issue.
class MyThread extends Thread {
MyThread(ThreadGroup tg, String name) {
super(tg, name);
}
boolean failed = false;
String failMessage = null;
public void run() {
SimpleThread st1 = null;
SimpleThread st2 = null;
ThreadGroup mytg = null;
Thread firstOne = null;
Thread secondOne = null;
try {
int arrayLength = 10;
Thread[] tarray = new Thread[arrayLength];
st1 = new SimpleThread(-1);
st2 = new SimpleThread(-1);
mytg = new ThreadGroup("jp");
firstOne = new Thread(mytg, st1, "firstOne2");
secondOne = new Thread(mytg, st2, "secondOne1");
int orgCount = Thread.enumerate(tarray);
synchronized (st1) {
firstOne.start();
try {
st1.wait();
} catch (InterruptedException e) {
}
}
int count = Thread.enumerate(tarray);
assertEquals("Incorrect value returned2",
orgCount + 1, count);
synchronized (st2) {
secondOne.start();
try {
st2.wait();
} catch (InterruptedException e) {
}
}
count = Thread.enumerate(tarray);
assertEquals("Incorrect value returned3",
orgCount + 2, count);
} catch (junit.framework.AssertionFailedError e) {
failed = true;
failMessage = e.getMessage();
e.printStackTrace();
} finally {
synchronized (st1) {
firstOne.interrupt();
}
synchronized (st2) {
secondOne.interrupt();
}
try {
firstOne.join();
secondOne.join();
} catch (InterruptedException e) {
}
mytg.destroy();
}
}
};
ThreadGroup tg = new ThreadGroup("tg");
MyThread t = new MyThread(tg, "top");
t.start();
try {
t.join();
} catch (InterruptedException e) {
fail("Unexpected interrupt");
} finally {
tg.destroy();
}
assertFalse(t.failMessage, t.failed);
}
/**
* @tests java.lang.Thread#getContextClassLoader()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getContextClassLoader",
args = {}
)
public void test_getContextClassLoader() {
// Test for method java.lang.ClassLoader
// java.lang.Thread.getContextClassLoader()
Thread t = new Thread();
assertNotNull(Thread.currentThread().getContextClassLoader());
assertTrue("Incorrect class loader returned",
t.getContextClassLoader() == Thread.currentThread()
.getContextClassLoader());
}
/**
* @tests java.lang.Thread#getName()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getName",
args = {}
)
public void test_getName() {
// Test for method java.lang.String java.lang.Thread.getName()
st = new Thread(new SimpleThread(1), "SimpleThread6");
assertEquals("Returned incorrect thread name",
"SimpleThread6", st.getName());
st.start();
}
/**
* @tests java.lang.Thread#getPriority()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getPriority",
args = {}
)
public void test_getPriority() {
// Test for method int java.lang.Thread.getPriority()
st = new Thread(new SimpleThread(1));
st.setPriority(Thread.MAX_PRIORITY);
assertTrue("Returned incorrect thread priority",
st.getPriority() == Thread.MAX_PRIORITY);
st.start();
}
/**
* @tests java.lang.Thread#getThreadGroup()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getThreadGroup",
args = {}
)
public void test_getThreadGroup() {
// Test for method java.lang.ThreadGroup
// java.lang.Thread.getThreadGroup()
ThreadGroup tg = new ThreadGroup("Test Group4");
st = new Thread(tg, /* new SimpleThread(1), */ "SimpleThread8");
assertTrue("Returned incorrect thread group", st.getThreadGroup() == tg);
st.start();
try {
st.join();
} catch (InterruptedException e) {
}
assertNull("group should be null", st.getThreadGroup());
assertNotNull("toString() should not be null", st.toString());
tg.destroy();
final Object lock = new Object();
Thread t = new Thread() {
@Override
public void run() {
synchronized (lock) {
lock.notifyAll();
}
}
};
synchronized (lock) {
t.start();
try {
lock.wait();
} catch (InterruptedException e) {
}
}
int running = 0;
while (t.isAlive())
running++;
ThreadGroup group = t.getThreadGroup();
assertNull("ThreadGroup is not null", group);
}
/**
* @tests java.lang.Thread#interrupt()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "interrupt",
args = {}
)
public void test_interrupt() {
// Test for method void java.lang.Thread.interrupt()
final Object lock = new Object();
class ChildThread1 extends Thread {
Thread parent;
boolean sync;
@Override
public void run() {
if (sync) {
synchronized (lock) {
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
}
}
}
parent.interrupt();
}
public ChildThread1(Thread p, String name, boolean sync) {
super(name);
parent = p;
this.sync = sync;
}
}
boolean interrupted = false;
try {
ct = new ChildThread1(Thread.currentThread(), "Interrupt Test1",
false);
synchronized (lock) {
ct.start();
lock.wait();
}
} catch (InterruptedException e) {
interrupted = true;
}
assertTrue("Failed to Interrupt thread1", interrupted);
interrupted = false;
try {
ct = new ChildThread1(Thread.currentThread(), "Interrupt Test2",
true);
synchronized (lock) {
ct.start();
lock.wait();
lock.notify();
}
Thread.sleep(20000);
} catch (InterruptedException e) {
interrupted = true;
}
assertTrue("Failed to Interrupt thread2", interrupted);
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
st = new Thread();
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.interrupt();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#interrupted()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "interrupted",
args = {}
)
public void test_interrupted() {
assertFalse("Interrupted returned true for non-interrupted thread", Thread
.interrupted());
Thread.currentThread().interrupt();
assertTrue("Interrupted returned true for non-interrupted thread", Thread.interrupted());
assertFalse("Failed to clear interrupted flag", Thread.interrupted());
}
/**
* @tests java.lang.Thread#isAlive()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "isAlive",
args = {}
)
public void test_isAlive() {
// Test for method boolean java.lang.Thread.isAlive()
SimpleThread simple;
st = new Thread(simple = new SimpleThread(500));
assertFalse("A thread that wasn't started is alive.", st.isAlive());
synchronized (simple) {
st.start();
try {
simple.wait();
} catch (InterruptedException e) {
}
}
assertTrue("Started thread returned false", st.isAlive());
try {
st.join();
} catch (InterruptedException e) {
fail("Thread did not die");
}
assertTrue("Stopped thread returned true", !st.isAlive());
}
/**
* @tests java.lang.Thread#isDaemon()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "isDaemon",
args = {}
)
public void test_isDaemon() {
// Test for method boolean java.lang.Thread.isDaemon()
st = new Thread(new SimpleThread(1), "SimpleThread10");
assertTrue("Non-Daemon thread returned true", !st.isDaemon());
st.setDaemon(true);
assertTrue("Daemon thread returned false", st.isDaemon());
st.start();
}
/**
* @tests java.lang.Thread#isInterrupted()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "isInterrupted",
args = {}
)
public void test_isInterrupted() {
// Test for method boolean java.lang.Thread.isInterrupted()
class SpinThread implements Runnable {
public volatile boolean done = false;
public void run() {
while (!Thread.currentThread().isInterrupted())
;
while (!done)
;
}
}
SpinThread spin = new SpinThread();
spinner = new Thread(spin);
spinner.start();
Thread.yield();
try {
assertTrue("Non-Interrupted thread returned true", !spinner
.isInterrupted());
spinner.interrupt();
assertTrue("Interrupted thread returned false", spinner
.isInterrupted());
spin.done = true;
} finally {
spinner.interrupt();
spin.done = true;
}
}
/**
* @tests java.lang.Thread#join()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "join",
args = {}
)
public void test_join() {
// Test for method void java.lang.Thread.join()
SimpleThread simple;
try {
st = new Thread(simple = new SimpleThread(100));
// cause isAlive() to be compiled by the JIT, as it must be called
// within 100ms below.
assertTrue("Thread is alive", !st.isAlive());
synchronized (simple) {
st.start();
simple.wait();
}
st.join();
} catch (InterruptedException e) {
fail("Join failed ");
}
assertTrue("Joined thread is still alive", !st.isAlive());
boolean result = true;
Thread th = new Thread("test");
try {
th.join();
} catch (InterruptedException e) {
result = false;
}
assertTrue("Hung joining a non-started thread", result);
th.start();
st = new Thread() {
public void run() {
try {
join();
fail("InterruptedException was not thrown.");
} catch(InterruptedException ie) {
//expected
}
}
};
st.start();
}
/**
* @tests java.lang.Thread#join(long)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "join",
args = {long.class}
)
public void test_joinJ() {
// Test for method void java.lang.Thread.join(long)
SimpleThread simple;
try {
st = new Thread(simple = new SimpleThread(1000), "SimpleThread12");
// cause isAlive() to be compiled by the JIT, as it must be called
// within 100ms below.
assertTrue("Thread is alive", !st.isAlive());
synchronized (simple) {
st.start();
simple.wait();
}
st.join(10);
} catch (InterruptedException e) {
fail("Join failed ");
}
assertTrue("Join failed to timeout", st.isAlive());
st.interrupt();
try {
st = new Thread(simple = new SimpleThread(100), "SimpleThread13");
synchronized (simple) {
st.start();
simple.wait();
}
st.join(1000);
} catch (InterruptedException e) {
fail("Join failed : " + e.getMessage());
return;
}
assertTrue("Joined thread is still alive", !st.isAlive());
final Object lock = new Object();
final Thread main = Thread.currentThread();
Thread killer = new Thread(new Runnable() {
public void run() {
try {
synchronized (lock) {
lock.notify();
}
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
main.interrupt();
}
});
boolean result = true;
Thread th = new Thread("test");
try {
synchronized (lock) {
killer.start();
lock.wait();
}
th.join(200);
} catch (InterruptedException e) {
result = false;
}
killer.interrupt();
assertTrue("Hung joining a non-started thread", result);
th.start();
st = new Thread() {
public void run() {
try {
join(1000);
fail("InterruptedException was not thrown.");
} catch(InterruptedException ie) {
//expected
}
}
};
st.start();
}
/**
* @tests java.lang.Thread#join(long, int)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "join",
args = {long.class, int.class}
)
public void test_joinJI() {
// Test for method void java.lang.Thread.join(long, int)
SimpleThread simple;
try {
st = new Thread(simple = new SimpleThread(1000), "Squawk1");
assertTrue("Thread is alive", !st.isAlive());
synchronized (simple) {
st.start();
simple.wait();
}
long firstRead = System.currentTimeMillis();
st.join(100, 999999);
long secondRead = System.currentTimeMillis();
assertTrue("Did not join by appropriate time: " + secondRead + "-"
+ firstRead + "=" + (secondRead - firstRead), secondRead
- firstRead <= 300);
assertTrue("Joined thread is not alive", st.isAlive());
st.interrupt();
} catch (Exception e) {
fail("Exception during test : " + e.getMessage());
}
final Object lock = new Object();
final Thread main = Thread.currentThread();
Thread killer = new Thread(new Runnable() {
public void run() {
try {
synchronized (lock) {
lock.notify();
}
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
main.interrupt();
}
});
boolean result = true;
Thread th = new Thread("test");
try {
synchronized (lock) {
killer.start();
lock.wait();
}
th.join(200, 20);
} catch (InterruptedException e) {
result = false;
}
killer.interrupt();
assertTrue("Hung joining a non-started thread", result);
th.start();
st = new Thread() {
public void run() {
try {
join(1000, 20);
fail("InterruptedException was not thrown.");
} catch(InterruptedException ie) {
//expected
}
}
};
st.start();
}
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setContextClassLoader",
args = {java.lang.ClassLoader.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getContextClassLoader",
args = {}
)
})
public void test_setContextClassLoader() {
PublicClassLoader pcl = new PublicClassLoader();
st = new Thread();
st.setContextClassLoader(pcl);
assertEquals(pcl, st.getContextClassLoader());
st.setContextClassLoader(null);
assertNull(st.getContextClassLoader());
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
if (perm.getName().equals("setContextClassLoader")
|| perm.getName().equals("getClassLoader") ) {
throw new SecurityException();
}
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.setContextClassLoader(pcl);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
private Thread launchFiveSecondDummyThread() {
Thread thread = new Thread() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Ignore
}
}
};
thread.start();
return thread;
}
private class ThreadSecurityManager extends SecurityManager {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
/**
* @tests java.lang.Thread#resume()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "resume",
args = {}
)
@AndroidOnly("RI does implement this method, whereas Android does not")
@SuppressWarnings("deprecation")
public void test_resume() {
Thread thread = launchFiveSecondDummyThread();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
// No-op in Android. Must neither have an effect nor throw an exception.
Thread.State state = thread.getState();
thread.resume();
assertEquals(state, thread.getState());
// Security checks are made even though method is not supported.
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(new ThreadSecurityManager());
try {
thread.resume();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
thread.join();
} catch (InterruptedException e) {
// Ignore
}
}
/**
* @tests java.lang.Thread#run()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "run",
args = {}
)
public void test_run() {
// Test for method void java.lang.Thread.run()
class RunThread implements Runnable {
boolean didThreadRun = false;
public void run() {
didThreadRun = true;
}
}
RunThread rt = new RunThread();
Thread t = new Thread(rt);
try {
t.start();
int count = 0;
while (!rt.didThreadRun && count < 20) {
Thread.sleep(100);
count++;
}
assertTrue("Thread did not run", rt.didThreadRun);
t.join();
} catch (InterruptedException e) {
assertTrue("Joined thread was interrupted", true);
}
assertTrue("Joined thread is still alive", !t.isAlive());
}
/**
* @tests java.lang.Thread#setDaemon(boolean)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setDaemon",
args = {boolean.class}
)
public void test_setDaemonZ() {
// Test for method void java.lang.Thread.setDaemon(boolean)
st = new Thread(new SimpleThread(1), "SimpleThread14");
st.setDaemon(true);
assertTrue("Failed to set thread as daemon thread", st.isDaemon());
st.start();
// BEGIN android-added
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.
}
// END android-added
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.setDaemon(false);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#setName(java.lang.String)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setName",
args = {java.lang.String.class}
)
public void test_setNameLjava_lang_String() {
// Test for method void java.lang.Thread.setName(java.lang.String)
st = new Thread(new SimpleThread(1), "SimpleThread15");
st.setName("Bogus Name");
assertEquals("Failed to set thread name",
"Bogus Name", st.getName());
try {
st.setName(null);
fail("Null should not be accepted as a valid name");
} catch (NullPointerException e) {
// success
assertTrue("Null should not be accepted as a valid name", true);
}
st.start();
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.setName("Bogus Name");
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#setPriority(int)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setPriority",
args = {int.class}
)
public void test_setPriorityI() {
// Test for method void java.lang.Thread.setPriority(int)
st = new Thread(new SimpleThread(1));
st.setPriority(Thread.MAX_PRIORITY);
assertTrue("Failed to set priority",
st.getPriority() == Thread.MAX_PRIORITY);
st.start();
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.setPriority(Thread.MIN_PRIORITY);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
st.setPriority(Thread.MIN_PRIORITY - 1);
fail("IllegalArgumentException is not thrown.");
} catch(IllegalArgumentException iae) {
//expected
}
try {
st.setPriority(Thread.MAX_PRIORITY + 1);
fail("IllegalArgumentException is not thrown.");
} catch(IllegalArgumentException iae) {
//expected
}
}
/**
* @tests java.lang.Thread#sleep(long)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "sleep",
args = {long.class}
)
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);
}
/**
* @tests java.lang.Thread#sleep(long, int)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "sleep",
args = {long.class, int.class}
)
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);
}
/**
* @tests java.lang.Thread#start()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "start",
args = {}
)
public void test_start() {
// Test for method void java.lang.Thread.start()
try {
ResSupThread t = new ResSupThread(Thread.currentThread());
synchronized (t) {
ct = new Thread(t, "Interrupt Test4");
ct.start();
t.wait();
}
assertTrue("Thread is not running1", ct.isAlive());
// Let the child thread get going.
int orgval = t.getCheckVal();
Thread.sleep(150);
assertTrue("Thread is not running2", orgval != t.getCheckVal());
ct.interrupt();
} catch (InterruptedException e) {
fail("Unexpected interrupt occurred");
}
Thread thr = new Thread();
thr.start();
try {
thr.start();
} catch(IllegalThreadStateException itse){
//expected
}
}
/**
* @tests java.lang.Thread#stop()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "stop",
args = {}
)
@AndroidOnly("RI does implement this method, whereas Android does not")
@SuppressWarnings("deprecation")
public void test_stop() {
Thread thread = launchFiveSecondDummyThread();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
// No-op in Android. Must neither have an effect nor throw an exception.
Thread.State state = thread.getState();
thread.stop();
assertEquals(state, thread.getState());
// Security checks are made even though method is not supported.
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(new ThreadSecurityManager());
try {
thread.stop();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
thread.join();
} catch (InterruptedException e) {
// Ignore
}
}
/**
* @tests java.lang.Thread#stop(java.lang.Throwable)
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "Verifies security.",
method = "stop",
args = {java.lang.Throwable.class}
)
@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
}
// No-op in Android. Must neither have an effect nor throw an exception.
Thread.State state = thread.getState();
thread.stop(new Exception("Oops!"));
assertEquals(state, thread.getState());
// Security checks are made even though method is not supported.
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
thread.stop();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
thread.join();
} catch (InterruptedException e) {
// Ignore
}
}
/**
* @tests java.lang.Thread#suspend()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "suspend",
args = {}
)
@AndroidOnly("RI does implement this method, whereas Android does not")
@SuppressWarnings("deprecation")
public void test_suspend() {
Thread thread = launchFiveSecondDummyThread();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
// No-op in Android. Must neither have an effect nor throw an exception.
Thread.State state = thread.getState();
thread.suspend();
assertEquals(state, thread.getState());
// Security checks are made even though method is not supported.
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(new ThreadSecurityManager());
try {
thread.suspend();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
thread.join();
} catch (InterruptedException e) {
// Ignore
}
}
/**
* @tests java.lang.Thread#toString()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "toString",
args = {}
)
public void test_toString() {
// Test for method java.lang.String java.lang.Thread.toString()
ThreadGroup tg = new ThreadGroup("Test Group5");
st = new Thread(tg, new SimpleThread(1), "SimpleThread17");
final String stString = st.toString();
final String expected = "Thread[SimpleThread17,5,Test Group5]";
assertTrue("Returned incorrect string: " + stString + "\t(expecting :"
+ expected + ")", stString.equals(expected));
st.start();
try {
st.join();
} catch (InterruptedException e) {
}
tg.destroy();
}
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "yield",
args = {}
)
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 ++;
}
}
}
/**
* @tests java.lang.Thread#getAllStackTraces()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getAllStackTraces",
args = {}
)
public void test_getAllStackTraces() {
Map<Thread, StackTraceElement[]> stMap = Thread.getAllStackTraces();
assertNotNull(stMap);
//TODO add security-based tests
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
if(perm.getName().equals("modifyThreadGroup")) {
throw new SecurityException();
}
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
Thread.getAllStackTraces();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#getDefaultUncaughtExceptionHandler
* @tests java.lang.Thread#setDefaultUncaughtExceptionHandler
*/
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setDefaultUncaughtExceptionHandler",
args = {java.lang.Thread.UncaughtExceptionHandler.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getDefaultUncaughtExceptionHandler",
args = {}
)
})
public void test_get_setDefaultUncaughtExceptionHandler() {
class Handler implements UncaughtExceptionHandler {
public void uncaughtException(Thread thread, Throwable ex) {
}
}
final Handler handler = new Handler();
Thread.setDefaultUncaughtExceptionHandler(handler);
assertSame(handler, Thread.getDefaultUncaughtExceptionHandler());
Thread.setDefaultUncaughtExceptionHandler(null);
assertNull(Thread.getDefaultUncaughtExceptionHandler());
//TODO add security-based tests
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
if(perm.getName().
equals("setDefaultUncaughtExceptionHandler")) {
throw new SecurityException();
}
}
};
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.setDefaultUncaughtExceptionHandler(handler);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#getStackTrace()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getStackTrace",
args = {}
)
public void test_getStackTrace() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
assertNotNull(stackTrace);
stack_trace_loop: {
for (int i = 0; i < stackTrace.length; i++) {
StackTraceElement e = stackTrace[i];
if (getClass().getName().equals(e.getClassName())) {
if ("test_getStackTrace".equals(e.getMethodName())) {
break stack_trace_loop;
}
}
}
fail("class and method not found in stack trace");
}
//TODO add security-based tests
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
if(perm.getName().
equals("getStackTrace")) {
throw new SecurityException();
}
}
};
st = new Thread();
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.getStackTrace();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#getState()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getState",
args = {}
)
public void test_getState() {
Thread.State state = Thread.currentThread().getState();
assertNotNull(state);
assertEquals(Thread.State.RUNNABLE, state);
final Semaphore sem = new Semaphore(0);
final Object lock = new Object();
Thread th = new Thread() {
@Override
public void run() {
while (!sem.hasQueuedThreads()) {}
sem.release();
while (run) {}
try {
sem.acquire();
} catch (InterruptedException e) {
fail("InterruptedException was thrown.");
}
synchronized (lock) {
lock.equals(new Object());
}
synchronized (lock) {
try {
sem.release();
lock.wait(Long.MAX_VALUE);
} catch (InterruptedException e) {
// expected
}
}
}
};
assertEquals(Thread.State.NEW, th.getState());
th.start();
try {
sem.acquire();
} catch (InterruptedException e) {
fail("InterruptedException was thrown.");
}
assertEquals(Thread.State.RUNNABLE, th.getState());
run = false;
while (!sem.hasQueuedThreads()){}
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());
}
try {
sem.acquire();
} catch (InterruptedException e) {
fail("InterruptedException was thrown.");
}
synchronized (lock) {
assertEquals(Thread.State.TIMED_WAITING, th.getState());
th.interrupt();
}
try {
th.join(1000);
} catch(InterruptedException ie) {
fail("InterruptedException was thrown.");
}
assertEquals(Thread.State.TERMINATED, th.getState());
}
boolean run = true;
/**
* @tests java.lang.Thread#getUncaughtExceptionHandler
* @tests java.lang.Thread#setUncaughtExceptionHandler
*/
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getUncaughtExceptionHandler",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setUncaughtExceptionHandler",
args = {java.lang.Thread.UncaughtExceptionHandler.class}
)
})
public void test_get_setUncaughtExceptionHandler() {
class Handler implements UncaughtExceptionHandler {
public void uncaughtException(Thread thread, Throwable ex) {
}
}
final Handler handler = new Handler();
Thread.currentThread().setUncaughtExceptionHandler(handler);
assertSame(handler, Thread.currentThread().getUncaughtExceptionHandler());
Thread.currentThread().setUncaughtExceptionHandler(null);
//TODO add security-based tests
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(Thread t) {
throw new SecurityException();
}
};
st = new Thread();
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
st.setUncaughtExceptionHandler(handler);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.Thread#getId()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getId",
args = {}
)
public void test_getId() {
assertTrue("current thread's ID is not positive", Thread.currentThread().getId() > 0);
//check all the current threads for positive IDs
Map<Thread, StackTraceElement[]> stMap = Thread.getAllStackTraces();
for (Thread thread : stMap.keySet()) {
assertTrue("thread's ID is not positive: " + thread.getName(), thread.getId() > 0);
}
}
/**
* @tests java.lang.Thread#holdLock()
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "holdsLock",
args = {java.lang.Object.class}
)
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
}
}
@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;
System.runFinalization();
} catch (Exception e) {
}
}
}