/*
* 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 dalvik.annotation.AndroidOnly;
//import dalvik.annotation.BrokenTest;
//import dalvik.annotation.TestLevel;
//import dalvik.annotation.TestTargetNew;
//import dalvik.annotation.TestTargetClass;
import java.security.Permission;
import java.util.Vector;
//@TestTargetClass(ThreadGroup.class)
public class ThreadGroupTest extends junit.framework.TestCase implements Thread.UncaughtExceptionHandler {
class MyThread extends Thread {
public volatile int heartBeat = 0;
public MyThread(ThreadGroup group, String name)
throws SecurityException, IllegalThreadStateException {
super(group, name);
}
@Override
public void run() {
while (true) {
heartBeat++;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
break;
}
}
}
public boolean isActivelyRunning() {
long MAX_WAIT = 100;
return isActivelyRunning(MAX_WAIT);
}
public boolean isActivelyRunning(long maxWait) {
int beat = heartBeat;
long start = System.currentTimeMillis();
do {
Thread.yield();
int beat2 = heartBeat;
if (beat != beat2) {
return true;
}
} while (System.currentTimeMillis() - start < maxWait);
return false;
}
}
private ThreadGroup rootThreadGroup = null;
private ThreadGroup initialThreadGroup = null;
/**
* @tests java.lang.ThreadGroup#ThreadGroup(java.lang.String)
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "ThreadGroup",
args = {java.lang.String.class}
)
*/
public void test_ConstructorLjava_lang_String() {
// Test for method java.lang.ThreadGroup(java.lang.String)
// Unfortunately we have to use other APIs as well as we test the
// constructor
ThreadGroup newGroup = null;
ThreadGroup initial = getInitialThreadGroup();
final String name = "Test name";
newGroup = new ThreadGroup(name);
assertTrue(
"Has to be possible to create a subgroup of current group using simple constructor",
newGroup.getParent() == initial);
assertTrue("Name has to be correct", newGroup.getName().equals(name));
// cleanup
newGroup.destroy();
newGroup = new ThreadGroup("");
assertEquals("", newGroup.getName());
newGroup = new ThreadGroup(null);
assertNull(newGroup.getName());
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
new ThreadGroup(name);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.ThreadGroup#ThreadGroup(java.lang.ThreadGroup,
* java.lang.String)
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "ThreadGroup",
args = {java.lang.ThreadGroup.class, java.lang.String.class}
)
*/
public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_String() {
// Test for method java.lang.ThreadGroup(java.lang.ThreadGroup,
// java.lang.String)
// Unfortunately we have to use other APIs as well as we test the
// constructor
ThreadGroup newGroup = null;
try {
newGroup = new ThreadGroup(null, null);
} catch (NullPointerException e) {
}
assertNull("Can't create a ThreadGroup with a null parent",
newGroup);
newGroup = new ThreadGroup(getInitialThreadGroup(), null);
assertTrue("Has to be possible to create a subgroup of current group",
newGroup.getParent() == Thread.currentThread().getThreadGroup());
// Lets start all over
newGroup.destroy();
newGroup = new ThreadGroup(getRootThreadGroup(), "a name here");
assertTrue("Has to be possible to create a subgroup of root group",
newGroup.getParent() == getRootThreadGroup());
// Lets start all over
newGroup.destroy();
try {
newGroup = new ThreadGroup(newGroup, "a name here");
} catch (IllegalThreadStateException e) {
newGroup = null;
}
assertNull("Can't create a subgroup of a destroyed group",
newGroup);
try {
new ThreadGroup(null, "name");
fail("NullPointerException is not thrown.");
} catch(NullPointerException npe) {
//expected
}
try {
new ThreadGroup(newGroup, null);
fail("NullPointerException is not thrown.");
} catch(NullPointerException npe) {
//expected
}
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
new ThreadGroup(getRootThreadGroup(), "a name here");
fail("SecurityException was not thrown.");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.ThreadGroup#activeCount()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "activeCount",
args = {}
)
*/
public void test_activeCount() {
// Test for method int java.lang.ThreadGroup.activeCount()
ThreadGroup tg = new ThreadGroup("activeCount");
Thread t1 = new Thread(tg, new Runnable() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
});
int beforeCount = tg.activeCount();
t1.start();
int afterCount = tg.activeCount();
assertTrue("count of active threads should be increased",
(afterCount - beforeCount) == 1);
t1.interrupt();
try {
t1.join();
} catch (InterruptedException e) {
}
// cleanup
tg.destroy();
}
/**
* @tests java.lang.ThreadGroup#activeGroupCount()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "activeGroupCount",
args = {}
)
*/
public void test_activeGroupCount() {
ThreadGroup tg = new ThreadGroup("group count");
assertEquals("Incorrect number of groups",
0, tg.activeGroupCount());
Thread t1 = new Thread(tg, new Runnable() {
public void run() {
}
});
assertEquals("Incorrect number of groups",
0, tg.activeGroupCount());
t1.start();
assertEquals("Incorrect number of groups",
0, tg.activeGroupCount());
new ThreadGroup(tg, "test group 1");
assertEquals("Incorrect number of groups",
1, tg.activeGroupCount());
new ThreadGroup(tg, "test group 2");
assertEquals("Incorrect number of groups",
2, tg.activeGroupCount());
}
/**
* @tests java.lang.ThreadGroup#allowThreadSuspension(boolean)
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "allowThreadSuspension",
args = {boolean.class}
)
*/
@SuppressWarnings("deprecation")
public void test_allowThreadSuspensionZ() {
ThreadGroup tg = new ThreadGroup("thread suspension");
assertTrue("Thread suspention can not be changed",
tg.allowThreadSuspension(false));
assertTrue("Thread suspention can not be changed",
tg.allowThreadSuspension(true));
}
/**
* @tests java.lang.ThreadGroup#checkAccess()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "checkAccess",
args = {}
)
*/
public void test_checkAccess() {
// Test for method void java.lang.ThreadGroup.checkAccess()
final ThreadGroup originalCurrent = getInitialThreadGroup();
ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
SecurityManager currentManager = System.getSecurityManager();
boolean passed = true;
try {
if (currentManager != null) {
testRoot.checkAccess();
}
} catch (SecurityException se) {
passed = false;
}
assertTrue("CheckAccess is no-op with no SecurityManager", passed);
testRoot.destroy();
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
testRoot.checkAccess();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/*
* Checks whether the current Thread is in the given list.
*/
private boolean inListOfThreads(Thread[] threads) {
for (int i = 0; i < threads.length; i++) {
if (Thread.currentThread() == threads[i]) {
return true;
}
}
return false;
}
/*
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "enumerate",
args = {java.lang.Thread[].class}
)
*/
public void test_enumerateLThreadArray() {
int numThreads = initialThreadGroup.activeCount();
Thread[] listOfThreads = new Thread[numThreads];
int countThread = initialThreadGroup.enumerate(listOfThreads);
assertEquals(numThreads, countThread);
assertTrue("Current thread must be in enumeration of threads",
inListOfThreads(listOfThreads));
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
initialThreadGroup.enumerate(listOfThreads);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/*
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "enumerate",
args = {java.lang.Thread[].class, boolean.class}
)
*/
public void test_enumerateLThreadArrayLZ() {
int numThreads = initialThreadGroup.activeCount();
Thread[] listOfThreads = new Thread[numThreads];
int countThread = initialThreadGroup.enumerate(listOfThreads, false);
assertEquals(numThreads, countThread);
countThread = initialThreadGroup.enumerate(listOfThreads, true);
assertEquals(numThreads, countThread);
assertTrue("Current thread must be in enumeration of threads",
inListOfThreads(listOfThreads));
ThreadGroup subGroup = new ThreadGroup(initialThreadGroup, "Test Group 1");
int subThreadsCount = 3;
Vector<MyThread> subThreads = populateGroupsWithThreads(subGroup,
subThreadsCount);
countThread = initialThreadGroup.enumerate(listOfThreads, true);
assertEquals(numThreads, countThread);
assertTrue("Current thread must be in enumeration of threads",
inListOfThreads(listOfThreads));
for(MyThread thr:subThreads) {
thr.start();
}
// lets give them some time to start
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
fail("Should not be interrupted");
}
int numThreads2 = initialThreadGroup.activeCount();
listOfThreads = new Thread[numThreads2];
assertEquals(numThreads + subThreadsCount, numThreads2);
countThread = initialThreadGroup.enumerate(listOfThreads, true);
assertEquals(numThreads2, countThread);
assertTrue("Current thread must be in enumeration of threads",
inListOfThreads(listOfThreads));
for(MyThread thr:subThreads) {
thr.interrupt();
}
// lets give them some time to die
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
fail("Should not be interrupted");
}
int numThreads3 = initialThreadGroup.activeCount();
listOfThreads = new Thread[numThreads3];
assertEquals(numThreads, numThreads3);
countThread = initialThreadGroup.enumerate(listOfThreads, false);
assertEquals(numThreads3, countThread);
assertTrue("Current thread must be in enumeration of threads",
inListOfThreads(listOfThreads));
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
initialThreadGroup.enumerate(listOfThreads, true);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/*
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "enumerate",
args = {java.lang.ThreadGroup[].class}
)
@BrokenTest("Fails in CTS environment, but passes in CoreTestRunner")
*/
public void test_enumerateLThreadGroupArray() {
int numGroupThreads = initialThreadGroup.activeGroupCount();
ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads];
int countGroupThread = initialThreadGroup.enumerate(listOfGroups);
assertEquals(numGroupThreads, countGroupThread);
ThreadGroup[] listOfGroups1 = new ThreadGroup[numGroupThreads + 1];
countGroupThread = initialThreadGroup.enumerate(listOfGroups1);
assertEquals(numGroupThreads, countGroupThread);
assertNull(listOfGroups1[listOfGroups1.length - 1]);
ThreadGroup[] listOfGroups2 = new ThreadGroup[numGroupThreads - 1];
countGroupThread = initialThreadGroup.enumerate(listOfGroups2);
assertEquals(numGroupThreads - 1, countGroupThread);
ThreadGroup thrGroup1 = new ThreadGroup("Test Group 1");
countGroupThread = thrGroup1.enumerate(listOfGroups);
assertEquals(0, countGroupThread);
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
initialThreadGroup.enumerate(listOfGroups);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/*
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "enumerate",
args = {java.lang.ThreadGroup[].class, boolean.class}
)
*/
public void test_enumerateLThreadGroupArrayLZ() {
ThreadGroup thrGroup = new ThreadGroup("Test Group 1");
Vector<MyThread> subThreads = populateGroupsWithThreads(thrGroup, 3);
int numGroupThreads = thrGroup.activeGroupCount();
ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads];
assertEquals(0, thrGroup.enumerate(listOfGroups, true));
assertEquals(0, thrGroup.enumerate(listOfGroups, false));
for(MyThread thr:subThreads) {
thr.start();
}
numGroupThreads = thrGroup.activeGroupCount();
listOfGroups = new ThreadGroup[numGroupThreads];
assertEquals(0, thrGroup.enumerate(listOfGroups, true));
assertEquals(0, thrGroup.enumerate(listOfGroups, false));
ThreadGroup subGroup1 = new ThreadGroup(thrGroup, "Test Group 2");
Vector<MyThread> subThreads1 = populateGroupsWithThreads(subGroup1, 3);
numGroupThreads = thrGroup.activeGroupCount();
listOfGroups = new ThreadGroup[numGroupThreads];
assertEquals(1, thrGroup.enumerate(listOfGroups, true));
assertEquals(1, thrGroup.enumerate(listOfGroups, false));
for(MyThread thr:subThreads1) {
thr.start();
}
numGroupThreads = thrGroup.activeGroupCount();
listOfGroups = new ThreadGroup[numGroupThreads];
assertEquals(1, thrGroup.enumerate(listOfGroups, true));
assertEquals(1, thrGroup.enumerate(listOfGroups, false));
for(MyThread thr:subThreads) {
thr.interrupt();
}
ThreadGroup subGroup2 = new ThreadGroup(subGroup1, "Test Group 3");
Vector<MyThread> subThreads2 = populateGroupsWithThreads(subGroup2, 3);
numGroupThreads = thrGroup.activeGroupCount();
listOfGroups = new ThreadGroup[numGroupThreads];
assertEquals(2, thrGroup.enumerate(listOfGroups, true));
assertEquals(1, thrGroup.enumerate(listOfGroups, false));
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
thrGroup.enumerate(listOfGroups, true);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.ThreadGroup#destroy()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "destroy",
args = {}
)
*/
public void test_destroy() {
// Test for method void java.lang.ThreadGroup.destroy()
final ThreadGroup originalCurrent = getInitialThreadGroup();
ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
final int DEPTH = 4;
final Vector<ThreadGroup> subgroups = buildRandomTreeUnder(testRoot, DEPTH);
// destroy them all
testRoot.destroy();
for (int i = 0; i < subgroups.size(); i++) {
ThreadGroup child = subgroups.elementAt(i);
assertEquals("Destroyed child can't have children", 0, child
.activeCount());
boolean passed = false;
try {
child.destroy();
} catch (IllegalThreadStateException e) {
passed = true;
}
assertTrue("Destroyed child can't be destroyed again", passed);
}
testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)");
testRoot.setDaemon(true);
ThreadGroup child = new ThreadGroup(testRoot, "daemon child");
// If we destroy the last daemon's child, the daemon should get destroyed
// as well
child.destroy();
boolean passed = false;
try {
child.destroy();
} catch (IllegalThreadStateException e) {
passed = true;
}
assertTrue("Daemon should have been destroyed already", passed);
passed = false;
try {
testRoot.destroy();
} catch (IllegalThreadStateException e) {
passed = true;
}
assertTrue("Daemon parent should have been destroyed automatically",
passed);
assertTrue(
"Destroyed daemon's child should not be in daemon's list anymore",
!arrayIncludes(groups(testRoot), child));
assertTrue("Destroyed daemon should not be in parent's list anymore",
!arrayIncludes(groups(originalCurrent), testRoot));
testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)");
testRoot.setDaemon(true);
Thread noOp = new Thread(testRoot, null, "no-op thread") {
@Override
public void run() {
}
};
noOp.start();
// Wait for the no-op thread to run inside daemon ThreadGroup
try {
noOp.join();
} catch (InterruptedException ie) {
fail("Should not be interrupted");
}
passed = false;
try {
child.destroy();
} catch (IllegalThreadStateException e) {
passed = true;
}
assertTrue(
"Daemon group should have been destroyed already when last thread died",
passed);
testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)");
noOp = new Thread(testRoot, null, "no-op thread") {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
fail("Should not be interrupted");
}
}
};
// Has to execute the next lines in an interval < the sleep interval of
// the no-op thread
noOp.start();
passed = false;
try {
testRoot.destroy();
} catch (IllegalThreadStateException its) {
passed = true;
}
assertTrue("Can't destroy a ThreadGroup that has threads", passed);
// But after the thread dies, we have to be able to destroy the thread
// group
try {
noOp.join();
} catch (InterruptedException ie) {
fail("Should not be interrupted");
}
passed = true;
try {
testRoot.destroy();
} catch (IllegalThreadStateException its) {
passed = false;
}
assertTrue(
"Should be able to destroy a ThreadGroup that has no threads",
passed);
ThreadGroup tg = new ThreadGroup("ThreadGroup");
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
originalCurrent.destroy();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.ThreadGroup#destroy()
@TestTargetNew(
level = TestLevel.PARTIAL,
notes = "Verifies IllegalThreadStateException.",
method = "destroy",
args = {}
)
*/
public void test_destroy_subtest0() {
ThreadGroup group1 = new ThreadGroup("test_destroy_subtest0");
group1.destroy();
try {
new Thread(group1, "test_destroy_subtest0");
fail("should throw IllegalThreadStateException");
} catch (IllegalThreadStateException e) {
}
}
/**
* @tests java.lang.ThreadGroup#getMaxPriority()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getMaxPriority",
args = {}
)
*/
public void test_getMaxPriority() {
// Test for method int java.lang.ThreadGroup.getMaxPriority()
final ThreadGroup originalCurrent = getInitialThreadGroup();
ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
boolean passed = true;
try {
testRoot.setMaxPriority(Thread.MIN_PRIORITY);
} catch (IllegalArgumentException iae) {
passed = false;
}
assertTrue("Should be able to set priority", passed);
assertTrue("New value should be the same as we set", testRoot
.getMaxPriority() == Thread.MIN_PRIORITY);
testRoot.destroy();
}
/**
* @tests java.lang.ThreadGroup#getName()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getName",
args = {}
)
*/
public void test_getName() {
// Test for method java.lang.String java.lang.ThreadGroup.getName()
final ThreadGroup originalCurrent = getInitialThreadGroup();
final String name = "Test group";
final ThreadGroup testRoot = new ThreadGroup(originalCurrent, name);
assertTrue("Setting a name&getting does not work", testRoot.getName()
.equals(name));
testRoot.destroy();
}
/**
* @tests java.lang.ThreadGroup#getParent()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "getParent",
args = {}
)
*/
public void test_getParent() {
// Test for method java.lang.ThreadGroup
// java.lang.ThreadGroup.getParent()
final ThreadGroup originalCurrent = getInitialThreadGroup();
ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
assertTrue("Parent is wrong", testRoot.getParent() == originalCurrent);
// Create some groups, nested some levels.
final int TOTAL_DEPTH = 5;
ThreadGroup current = testRoot;
Vector<ThreadGroup> groups = new Vector<ThreadGroup>();
// To maintain the invariant that a thread in the Vector is parent
// of the next one in the collection (and child of the previous one)
groups.addElement(testRoot);
for (int i = 0; i < TOTAL_DEPTH; i++) {
current = new ThreadGroup(current, "level " + i);
groups.addElement(current);
}
// Now we walk the levels down, checking if parent is ok
for (int i = 1; i < groups.size(); i++) {
current = groups.elementAt(i);
ThreadGroup previous = groups.elementAt(i - 1);
assertTrue("Parent is wrong", current.getParent() == previous);
}
final ThreadGroup[] checkAccessGroup = new ThreadGroup[1];
class SecurityManagerImpl extends MutableSecurityManager {
@Override
public void checkAccess(ThreadGroup group) {
checkAccessGroup[0] = group;
}
}
SecurityManagerImpl sm = new SecurityManagerImpl();
//add permission to allow reset of security manager
sm.addPermission(MutableSecurityManager.SET_SECURITY_MANAGER);
ThreadGroup parent;
try {
// To see if it checks Thread creation with our SecurityManager
System.setSecurityManager(sm);
parent = testRoot.getParent();
} finally {
// restore original, no side-effects
System.setSecurityManager(null);
}
assertTrue("checkAccess with incorrect group",
checkAccessGroup[0] == parent);
testRoot.destroy();
}
/**
* @tests java.lang.ThreadGroup#interrupt()
private static boolean interrupted = false;
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "interrupt",
args = {}
)
*/
public void test_interrupt() {
Thread.setDefaultUncaughtExceptionHandler(this);
ThreadGroup tg = new ThreadGroup("interrupt");
Thread t1 = new Thread(tg, new Runnable() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
fail("ok");
}
}
});
assertFalse("Incorrect state of thread", interrupted);
t1.start();
assertFalse("Incorrect state of thread", interrupted);
t1.interrupt();
try {
t1.join();
} catch (InterruptedException e) {
}
assertTrue("Incorrect state of thread", interrupted);
tg.destroy();
ThreadGroup threadGroup = new ThreadGroup("securityCheck");
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
threadGroup.interrupt();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.ThreadGroup#isDaemon()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "isDaemon",
args = {}
)
*/
public void test_isDaemon() {
// Test for method boolean java.lang.ThreadGroup.isDaemon()
daemonTests();
}
/**
* @tests java.lang.ThreadGroup#isDestroyed()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "isDestroyed",
args = {}
)
*/
public void test_isDestroyed() {
final ThreadGroup originalCurrent = getInitialThreadGroup();
final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
"Test group");
assertFalse("Test group is not destroyed yet",
testRoot.isDestroyed());
testRoot.destroy();
assertTrue("Test group already destroyed",
testRoot.isDestroyed());
}
/**
* @tests java.lang.ThreadGroup#list()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "list",
args = {}
)
*/
public void test_list() {
// Test for method void java.lang.ThreadGroup.list()
final ThreadGroup originalCurrent = getInitialThreadGroup();
// wipeSideEffectThreads destroy all side effect of threads created in
// java.lang.Thread
boolean result = wipeSideEffectThreads(originalCurrent);
if (result == false) {
fail("wipe threads in test_list() not successful");
}
final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
"Test group");
// First save the original System.out
java.io.PrintStream originalOut = System.out;
try {
java.io.ByteArrayOutputStream contentsStream = new java.io.ByteArrayOutputStream(
100);
java.io.PrintStream newOut = new java.io.PrintStream(contentsStream);
// We have to "redirect" System.out to test the method 'list'
System.setOut(newOut);
originalCurrent.list();
/*
* The output has to look like this
*
* java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main]
* java.lang.ThreadGroup[name=Test group,maxpri=10]
*
*/
String contents = new String(contentsStream.toByteArray());
boolean passed = (contents.indexOf("ThreadGroup[name=main") != -1) &&
(contents.indexOf("Thread[") != -1) &&
(contents.indexOf("ThreadGroup[name=Test group") != -1);
assertTrue("'list()' does not print expected contents. "
+ "Result from list: "
+ contents, passed);
// Do proper cleanup
testRoot.destroy();
} finally {
// No matter what, we need to restore the original System.out
System.setOut(originalOut);
}
}
/**
* @tests java.lang.ThreadGroup#parentOf(java.lang.ThreadGroup)
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "parentOf",
args = {java.lang.ThreadGroup.class}
)
*/
public void test_parentOfLjava_lang_ThreadGroup() {
// Test for method boolean
// java.lang.ThreadGroup.parentOf(java.lang.ThreadGroup)
final ThreadGroup originalCurrent = getInitialThreadGroup();
final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
"Test group");
final int DEPTH = 4;
buildRandomTreeUnder(testRoot, DEPTH);
final ThreadGroup[] allChildren = allGroups(testRoot);
for (ThreadGroup element : allChildren) {
assertTrue("Have to be parentOf all children", testRoot
.parentOf(element));
}
assertTrue("Have to be parentOf itself", testRoot.parentOf(testRoot));
testRoot.destroy();
assertTrue("Parent can't have test group as subgroup anymore",
!arrayIncludes(groups(testRoot.getParent()), testRoot));
try {
System.setSecurityManager(new MutableSecurityManager(MutableSecurityManager.SET_SECURITY_MANAGER));
assertTrue("Should not be parent", !testRoot
.parentOf(originalCurrent));
} finally {
System.setSecurityManager(null);
}
}
/**
* @tests java.lang.ThreadGroup#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() {
ThreadGroup group = new ThreadGroup("Foo");
Thread thread = launchFiveSecondDummyThread(group);
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();
group.resume();
assertEquals(state, thread.getState());
// Security checks are made even though method is not supported.
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(new ThreadSecurityManager());
try {
group.resume();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
thread.join();
} catch (InterruptedException e) {
// Ignore
}
}
/**
* @tests java.lang.ThreadGroup#setDaemon(boolean)
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setDaemon",
args = {boolean.class}
)
*/
public void test_setDaemonZ() {
// Test for method void java.lang.ThreadGroup.setDaemon(boolean)
daemonTests();
final ThreadGroup testRoot = new ThreadGroup("Test group");
testRoot.setDaemon(true);
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
new ThreadGroup("");
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.ThreadGroup#setMaxPriority(int)
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "setMaxPriority",
args = {int.class}
)
*/
public void test_setMaxPriorityI() {
// Test for method void java.lang.ThreadGroup.setMaxPriority(int)
final ThreadGroup originalCurrent = getInitialThreadGroup();
ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
boolean passed;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int currentMax = testRoot.getMaxPriority();
testRoot.setMaxPriority(Thread.MAX_PRIORITY + 1);
passed = testRoot.getMaxPriority() == currentMax;
assertTrue(
"setMaxPriority: Any value higher than the current one is ignored. Before: "
+ currentMax + " , after: " + testRoot.getMaxPriority(),
passed);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
currentMax = testRoot.getMaxPriority();
testRoot.setMaxPriority(Thread.MIN_PRIORITY - 1);
passed = testRoot.getMaxPriority() == Thread.MIN_PRIORITY;
assertTrue(
"setMaxPriority: Any value smaller than MIN_PRIORITY is adjusted to MIN_PRIORITY. Before: "
+ currentMax + " , after: " + testRoot.getMaxPriority(),
passed);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
testRoot.destroy();
testRoot = new ThreadGroup(originalCurrent, "Test group");
// Create some groups, nested some levels. Each level will have maxPrio
// 1 unit smaller than the parent's. However, there can't be a group
// with priority < Thread.MIN_PRIORITY
final int TOTAL_DEPTH = testRoot.getMaxPriority() - Thread.MIN_PRIORITY
- 2;
ThreadGroup current = testRoot;
for (int i = 0; i < TOTAL_DEPTH; i++) {
current = new ThreadGroup(current, "level " + i);
}
// Now we walk the levels down, changing the maxPrio and later verifying
// that the value is indeed 1 unit smaller than the parent's maxPrio.
int maxPrio, parentMaxPrio;
current = testRoot;
// To maintain the invariant that when we are to modify a child,
// its maxPriority is always 1 unit smaller than its parent's.
// We have to set it for the root manually, and the loop does the rest
// for all the other sub-levels
current.setMaxPriority(current.getParent().getMaxPriority() - 1);
for (int i = 0; i < TOTAL_DEPTH; i++) {
maxPrio = current.getMaxPriority();
parentMaxPrio = current.getParent().getMaxPriority();
ThreadGroup[] children = groups(current);
assertEquals("Can only have 1 subgroup", 1, children.length);
current = children[0];
assertTrue(
"Had to be 1 unit smaller than parent's priority in iteration="
+ i + " checking->" + current,
maxPrio == parentMaxPrio - 1);
current.setMaxPriority(maxPrio - 1);
// The next test is sort of redundant, since in next iteration it
// will be the parent tGroup, so the test will be done.
assertTrue("Had to be possible to change max priority", current
.getMaxPriority() == maxPrio - 1);
}
assertTrue(
"Priority of leaf child group has to be much smaller than original root group",
current.getMaxPriority() == testRoot.getMaxPriority()
- TOTAL_DEPTH);
testRoot.destroy();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
passed = true;
testRoot = new ThreadGroup(originalCurrent, "Test group");
try {
testRoot.setMaxPriority(Thread.MAX_PRIORITY);
} catch (IllegalArgumentException iae) {
passed = false;
}
assertTrue(
"Max Priority = Thread.MAX_PRIORITY should be possible if the test is run with default system ThreadGroup as root",
passed);
testRoot.destroy();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
passed = true;
testRoot = new ThreadGroup(originalCurrent, "Test group");
System.setSecurityManager(new MutableSecurityManager(MutableSecurityManager.SET_SECURITY_MANAGER));
try {
try {
testRoot.setMaxPriority(Thread.MIN_PRIORITY);
} catch (IllegalArgumentException iae) {
passed = false;
}
} finally {
System.setSecurityManager(null);
}
assertTrue(
"Min Priority = Thread.MIN_PRIORITY should be possible, always",
passed);
testRoot.destroy();
try {
System.setSecurityManager(new MutableSecurityManager(MutableSecurityManager.SET_SECURITY_MANAGER));
originalCurrent.setMaxPriority(Thread.MAX_PRIORITY);
} finally {
System.setSecurityManager(null);
}
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(sm);
try {
testRoot.setMaxPriority(Thread.MAX_PRIORITY);
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
}
/**
* @tests java.lang.ThreadGroup#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() {
ThreadGroup group = new ThreadGroup("Foo");
Thread thread = launchFiveSecondDummyThread(group);
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();
group.stop();
assertEquals(state, thread.getState());
// Security checks are made even though method is not supported.
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(new ThreadSecurityManager());
try {
group.stop();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
thread.join();
} catch (InterruptedException e) {
// Ignore
}
}
private Thread launchFiveSecondDummyThread(ThreadGroup group) {
Thread thread = new Thread(group, "Bar") {
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.ThreadGroup#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() {
ThreadGroup group = new ThreadGroup("Foo");
Thread thread = launchFiveSecondDummyThread(group);
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();
group.suspend();
assertEquals(state, thread.getState());
// Security checks are made even though method is not supported.
SecurityManager oldSm = System.getSecurityManager();
System.setSecurityManager(new ThreadSecurityManager());
try {
group.suspend();
fail("Should throw SecurityException");
} catch (SecurityException e) {
// expected
} finally {
System.setSecurityManager(oldSm);
}
try {
thread.join();
} catch (InterruptedException e) {
// Ignore
}
}
/**
* @tests java.lang.ThreadGroup#toString()
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "toString",
args = {}
)
*/
public void test_toString() {
// Test for method java.lang.String java.lang.ThreadGroup.toString()
final ThreadGroup originalCurrent = getInitialThreadGroup();
final String tGroupName = "Test group";
// Our own subclass
class MyThreadGroup extends ThreadGroup {
// Have to define a constructor since there's no default one
public MyThreadGroup(ThreadGroup parent, String name) {
super(parent, name);
}
}
;
ThreadGroup testRoot = new MyThreadGroup(originalCurrent, tGroupName);
final String toString = testRoot.toString();
StringBuffer expectedResult = new StringBuffer();
expectedResult.append(testRoot.getClass().getName());
expectedResult.append("[name=");
expectedResult.append(tGroupName);
expectedResult.append(",maxpri=");
expectedResult.append(testRoot.getMaxPriority());
expectedResult.append("]");
String expectedValue = expectedResult.toString();
assertTrue("toString does not follow the Java language spec.", toString
.equals(expectedValue));
testRoot.destroy();
}
/**
* @tests java.lang.ThreadGroup#uncaughtException(java.lang.Thread,
* java.lang.Throwable)
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
method = "uncaughtException",
args = {java.lang.Thread.class, java.lang.Throwable.class}
)
*/
@SuppressWarnings("deprecation")
public void test_uncaughtExceptionLjava_lang_ThreadLjava_lang_Throwable() {
// Test for method void
// java.lang.ThreadGroup.uncaughtException(java.lang.Thread,
// java.lang.Throwable)
final ThreadGroup originalCurrent = getInitialThreadGroup();
// indices for the array defined below
final int TEST_DEATH = 0;
final int TEST_OTHER = 1;
final int TEST_EXCEPTION_IN_UNCAUGHT = 2;
final int TEST_OTHER_THEN_DEATH = 3;
final int TEST_FORCING_THROW_THREAD_DEATH = 4;
final int TEST_KILLING = 5;
final int TEST_DEATH_AFTER_UNCAUGHT = 6;
final boolean[] passed = new boolean[] { false, false, false, false,
false, false, false };
ThreadGroup testRoot;
Thread thread;
// Our own exception class
class TestException extends RuntimeException {
private static final long serialVersionUID = 1L;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - -
testRoot = new ThreadGroup(originalCurrent,
"Test Forcing a throw of ThreadDeath") {
@Override
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof ThreadDeath) {
passed[TEST_FORCING_THROW_THREAD_DEATH] = true;
}
// always forward, any exception
super.uncaughtException(t, e);
}
};
// Test if a Thread tells its ThreadGroup about ThreadDeath
thread = new Thread(testRoot, null, "suicidal thread") {
@Override
public void run() {
throw new ThreadDeath();
}
};
thread.start();
try {
thread.join();
} catch (InterruptedException ie) {
fail("Should not have been interrupted");
}
testRoot.destroy();
assertTrue(
"Any thread should notify its ThreadGroup about its own death, even if suicide:"
+ testRoot, passed[TEST_FORCING_THROW_THREAD_DEATH]);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - -
testRoot = new ThreadGroup(originalCurrent, "Test ThreadDeath") {
@Override
public void uncaughtException(Thread t, Throwable e) {
passed[TEST_DEATH] = false;
// always forward, any exception
super.uncaughtException(t, e);
}
};
// Test if a Thread tells its ThreadGroup about ThreadDeath
passed[TEST_DEATH] = true;
thread = new Thread(testRoot, null, "no-op thread");
thread.start();
try {
thread.join();
} catch (InterruptedException ie) {
fail("Should not have been interrupted");
}
testRoot.destroy();
assertTrue("A thread should not call uncaughtException when it dies:"
+ testRoot, passed[TEST_DEATH]);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - -
testRoot = new ThreadGroup(originalCurrent, "Test other Exception") {
@Override
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof TestException) {
passed[TEST_OTHER] = true;
} else {
// only forward exceptions other than our test
super.uncaughtException(t, e);
}
}
};
// Test if a Thread tells its ThreadGroup about an Exception
thread = new Thread(testRoot, null, "no-op thread") {
@Override
public void run() {
throw new TestException();
}
};
thread.start();
try {
thread.join();
} catch (InterruptedException ie) {
fail("Should not have been interrupted");
}
testRoot.destroy();
assertTrue(
"Any thread should notify its ThreadGroup about an uncaught exception:"
+ testRoot, passed[TEST_OTHER]);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - -
// Our own uncaught exception class
class UncaughtException extends TestException {
private static final long serialVersionUID = 1L;
}
testRoot = new ThreadGroup(originalCurrent,
"Test Exception in uncaught exception") {
@Override
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof TestException) {
passed[TEST_EXCEPTION_IN_UNCAUGHT] = true;
// Let's simulate an error inside our uncaughtException
// method.
// This should be no-op according to the spec
throw new UncaughtException();
}
// only forward exceptions other than our test
super.uncaughtException(t, e);
}
};
// Test if an Exception in uncaughtException is really a no-op
thread = new Thread(testRoot, null, "no-op thread") {
@Override
public void run() {
try {
throw new TestException();
} catch (UncaughtException ue) {
// any exception in my ThreadGroup's uncaughtException must
// not be propagated.
// If it gets propagated and we detected that, the test failed
passed[TEST_EXCEPTION_IN_UNCAUGHT] = false;
}
}
};
thread.start();
try {
thread.join();
} catch (InterruptedException ie) {
fail("Should not have been interrupted");
}
testRoot.destroy();
assertTrue(
"Any uncaughtException in uncaughtException should be no-op:"
+ testRoot, passed[TEST_EXCEPTION_IN_UNCAUGHT]);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - -
// This is a mix of 2 of the tests above. It is assumed that ThreadDeath
// and any random exception do work , tested separately. Now we test
// if after an uncaughtException is forwarded to the ThreadGroup and
// the Thread dies, if ThreadDeath is also forwarded. It should be
// (so that a ThreadGroup can know its Thread died)
testRoot = new ThreadGroup(originalCurrent,
"Test Uncaught followed by ThreadDeath") {
@Override
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof ThreadDeath) {
passed[TEST_DEATH_AFTER_UNCAUGHT] = true;
}
if (e instanceof TestException) {
passed[TEST_OTHER_THEN_DEATH] = true;
} else {
// only forward exceptions other than our test
super.uncaughtException(t, e);
}
}
};
// Test if a Thread tells its ThreadGroup about an Exception and also
// ThreadDeath
thread = new Thread(testRoot, null, "no-op thread") {
@Override
public void run() {
throw new TestException();
}
};
thread.start();
try {
thread.join();
} catch (InterruptedException ie) {
fail("Should not have been interrupted");
}
testRoot.destroy();
}
/*
* @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable)
*/
public void uncaughtException(Thread t, Throwable e) {
interrupted = true;
Thread.setDefaultUncaughtExceptionHandler(null);
}
@Override
protected void setUp() {
initialThreadGroup = Thread.currentThread().getThreadGroup();
rootThreadGroup = initialThreadGroup;
while (rootThreadGroup.getParent() != null) {
rootThreadGroup = rootThreadGroup.getParent();
}
}
@Override
protected void tearDown() {
try {
// Give the threads a chance to die.
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
private Thread[] threads(ThreadGroup parent) {
// No API to get the count of immediate children only ?
int count = parent.activeCount();
Thread[] all = new Thread[count];
int actualSize = parent.enumerate(all, false);
Thread[] result;
if (actualSize == all.length) {
result = all;
} else {
result = new Thread[actualSize];
System.arraycopy(all, 0, result, 0, actualSize);
}
return result;
}
private ThreadGroup getInitialThreadGroup() {
return initialThreadGroup;
}
private ThreadGroup[] allGroups(ThreadGroup parent) {
int count = parent.activeGroupCount();
ThreadGroup[] all = new ThreadGroup[count];
parent.enumerate(all, true);
return all;
}
private void daemonTests() {
// Test for method void java.lang.ThreadGroup.setDaemon(boolean)
final ThreadGroup originalCurrent = getInitialThreadGroup();
final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
"Test group");
testRoot.setDaemon(true);
assertTrue("Setting daemon&getting does not work", testRoot.isDaemon());
testRoot.setDaemon(false);
assertTrue("Setting daemon&getting does not work", !testRoot.isDaemon());
testRoot.destroy();
}
private boolean wipeAllThreads(final ThreadGroup aGroup) {
boolean ok = true;
Thread[] threads = threads(aGroup);
for (Thread t : threads) {
ok = ok && wipeThread(t);
}
// Recursively for subgroups (if any)
ThreadGroup[] children = groups(aGroup);
for (ThreadGroup element : children) {
ok = ok && wipeAllThreads(element);
}
return ok;
}
private boolean wipeSideEffectThreads(ThreadGroup aGroup) {
boolean ok = true;
Thread[] threads = threads(aGroup);
for (Thread t : threads) {
if (t.getName().equals("SimpleThread")
|| t.getName().equals("Bogus Name")
|| t.getName().equals("Testing")
|| t.getName().equals("foo")
|| t.getName().equals("Test Group")
|| t.getName().equals("Squawk")
|| t.getName().equals("Thread-1")
|| t.getName().equals("firstOne")
|| t.getName().equals("secondOne")
|| t.getName().equals("Thread-16")
|| t.getName().equals("Thread-14")) {
ok = ok && wipeThread(t);
}
}
// Recursively for subgroups (if any)
ThreadGroup[] children = groups(aGroup);
for (ThreadGroup element : children) {
ok = ok && wipeSideEffectThreads(element);
if(element.getName() != null) {
if (element.getName().equals("Test Group")
|| element.getName().equals("foo")
|| element.getName().equals("jp")) {
element.destroy();
}
}
}
try {
// Give the threads a chance to die.
Thread.sleep(50);
} catch (InterruptedException e) {
}
return ok;
}
private void asyncBuildRandomTreeUnder(final ThreadGroup aGroup,
final int depth, final Vector<ThreadGroup> allCreated) {
if (depth <= 0) {
return;
}
final int maxImmediateSubgroups = random(3);
for (int i = 0; i < maxImmediateSubgroups; i++) {
final int iClone = i;
final String name = " Depth = " + depth + ",N = " + iClone
+ ",Vector size at creation: " + allCreated.size();
// Use concurrency to maximize chance of exposing concurrency bugs
// in ThreadGroups
Thread t = new Thread(aGroup, name) {
@Override
public void run() {
ThreadGroup newGroup = new ThreadGroup(aGroup, name);
allCreated.addElement(newGroup);
asyncBuildRandomTreeUnder(newGroup, depth - 1, allCreated);
}
};
t.start();
}
}
private Vector<ThreadGroup> asyncBuildRandomTreeUnder(final ThreadGroup aGroup,
final int depth) {
Vector<ThreadGroup> result = new Vector<ThreadGroup>();
asyncBuildRandomTreeUnder(aGroup, depth, result);
return result;
}
private boolean allSuspended(Vector<MyThread> threads) {
for (int i = 0; i < threads.size(); i++) {
MyThread t = threads.elementAt(i);
if (t.isActivelyRunning()) {
return false;
}
}
return true;
}
private ThreadGroup[] groups(ThreadGroup parent) {
// No API to get the count of immediate children only ?
int count = parent.activeGroupCount();
ThreadGroup[] all = new ThreadGroup[count];
parent.enumerate(all, false);
// Now we may have nulls in the array, we must find the actual size
int actualSize = 0;
for (; actualSize < all.length; actualSize++) {
if (all[actualSize] == null) {
break;
}
}
ThreadGroup[] result;
if (actualSize == all.length) {
result = all;
} else {
result = new ThreadGroup[actualSize];
System.arraycopy(all, 0, result, 0, actualSize);
}
return result;
}
private Vector<MyThread> populateGroupsWithThreads(final ThreadGroup aGroup,
final int threadCount) {
Vector<MyThread> result = new Vector<MyThread>();
populateGroupsWithThreads(aGroup, threadCount, result);
return result;
}
private void populateGroupsWithThreads(final ThreadGroup aGroup,
final int threadCount, final Vector<MyThread> allCreated) {
for (int i = 0; i < threadCount; i++) {
final int iClone = i;
final String name = "(MyThread)N =" + iClone + "/" + threadCount
+ " ,Vector size at creation: " + allCreated.size();
MyThread t = new MyThread(aGroup, name);
allCreated.addElement(t);
}
// Recursively for subgroups (if any)
ThreadGroup[] children = groups(aGroup);
for (ThreadGroup element : children) {
populateGroupsWithThreads(element, threadCount, allCreated);
}
}
private int random(int max) {
return 1 + ((new Object()).hashCode() % max);
}
@SuppressWarnings("deprecation")
private boolean wipeThread(Thread t) {
t.stop();
try {
t.join(1000);
} catch (InterruptedException ie) {
fail("Should not have been interrupted");
}
// The thread had plenty (subjective) of time to die so there
// is a problem.
if (t.isAlive()) {
return false;
}
return true;
}
private Vector<ThreadGroup> buildRandomTreeUnder(ThreadGroup aGroup, int depth) {
Vector<ThreadGroup> result = asyncBuildRandomTreeUnder(aGroup, depth);
while (true) {
int sizeBefore = result.size();
try {
Thread.sleep(1000);
int sizeAfter = result.size();
// If no activity for a while, we assume async building may be
// done.
if (sizeBefore == sizeAfter) {
// It can only be done if no more threads. Unfortunately we
// are relying on this API to work as well.
// If it does not, we may loop forever.
if (aGroup.activeCount() == 0) {
break;
}
}
} catch (InterruptedException e) {
}
}
return result;
}
private boolean arrayIncludes(Object[] array, Object toTest) {
for (Object element : array) {
if (element == toTest) {
return true;
}
}
return false;
}
protected void myassertTrue(String msg, boolean b) {
// This method is defined here just to solve a visibility problem
// of protected methods with inner types
assertTrue(msg, b);
}
private ThreadGroup getRootThreadGroup() {
return rootThreadGroup;
}
SecurityManager sm = new SecurityManager() {
public void checkPermission(Permission perm) {
}
public void checkAccess(ThreadGroup g) {
throw new SecurityException();
}
};
}