You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by sm...@apache.org on 2006/08/29 07:40:47 UTC

svn commit: r437974 [17/19] - /incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java?rev=437974&r1=437973&r2=437974&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java Mon Aug 28 22:40:44 2006
@@ -1,1519 +1,1519 @@
-/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.luni.tests.java.lang;
-
-import java.util.Vector;
-
-public class ThreadGroupTest extends junit.framework.TestCase {
-
-	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) {
-				}
-			}
-		}
-
-		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)
-	 */
-	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();
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.ThreadGroup,
-	 *        java.lang.String)
-	 */
-	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);
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#activeCount()
-	 */
-	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 count = tg.activeCount();
-		assertTrue("wrong active count: " + count, count == 0);
-		t1.start();
-		count = tg.activeCount();
-		assertTrue("wrong active count: " + count, count == 1);
-		t1.interrupt();
-		try {
-			t1.join();
-		} catch (InterruptedException e) {
-		}
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#checkAccess()
-	 */
-	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();
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#destroy()
-	 */
-	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);
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#destroy()
-	 */
-	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()
-	 */
-	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;
-		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()
-	 */
-	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()
-	 */
-	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#isDaemon()
-	 */
-	public void test_isDaemon() {
-		// Test for method boolean java.lang.ThreadGroup.isDaemon()
-
-		daemonTests();
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#list()
-	 */
-	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) {
-            System.out.println("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();
-			byte[] contents = contentsStream.toByteArray();
-
-			/*
-			 * 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]
-			 * 
-			 */
-
-			boolean passed = verifyThreadList(originalCurrent, testRoot,
-					contents);
-
-			assertTrue(
-					"Either 'list' is wrong or other tests are leaving side-effects.\n"
-							+ "Result from list:\n " + "-----------------\n "
-							+ new String(contents, 0, contents.length)
-							+ "\n-----------------\n ", 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)
-	 */
-	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()
-	 */
-	@SuppressWarnings("deprecation")
-    public void test_resume() throws OutOfMemoryError {
-		// Test for method void java.lang.ThreadGroup.resume()
-
-		final ThreadGroup originalCurrent = getInitialThreadGroup();
-
-		final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
-				"Test group");
-		final int DEPTH = 2;
-		buildRandomTreeUnder(testRoot, DEPTH);
-
-		final int THREADS_PER_GROUP = 2;
-		final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
-				THREADS_PER_GROUP);
-
-		boolean[] isResumed = null;
-		try {
-			try {
-				for (int i = 0; i < threads.size(); i++) {
-					Thread t = threads.elementAt(i);
-					t.start();
-					t.suspend();
-				}
-				// In 5.0, activeCount() only returns threads that are alive
-				assertTrue("Internal error when populating ThreadGroups", testRoot
-						.activeCount() == threads.size());
-			} catch (OutOfMemoryError e) {
-				for (int i = 0; i < threads.size(); i++) {
-					Thread t = threads.elementAt(i);
-					t.resume();
-					t.stop(); // deprecated but effective
-				}
-				throw e;
-			}
-
-			// Now that they are all suspended, let's resume the ThreadGroup
-			testRoot.resume();
-
-			// Give them some time to really resume
-			try {
-				Thread.sleep(500);
-			} catch (InterruptedException ie) {
-				fail("Should not have been interrupted");
-			}
-
-			isResumed = new boolean[threads.size()];
-			boolean failed = false;
-			for (int i = 0; i < isResumed.length; i++) {
-				MyThread t = threads.elementAt(i);
-				if (!failed) { // if one failed, don't waste time checking the
-					// rest
-					isResumed[i] = t.isActivelyRunning(1000);
-					failed = failed | (!isResumed[i]);
-				}
-				t.stop(); // deprecated but effective
-			}
-
-			// Give them some time to really die
-			try {
-				Thread.sleep(500);
-			} catch (InterruptedException ie) {
-				fail("Should not have been interrupted");
-			}
-		} finally {
-			// Make sure we do cleanup before returning
-			testRoot.destroy();
-		}
-
-		for (int i = 0; i < isResumed.length; i++) {
-			assertTrue("Thread " + threads.elementAt(i)
-					+ " was not running when it was killed", isResumed[i]);
-		}
-
-		assertEquals("Method destroy must have problems",
-				0, testRoot.activeCount());
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#setDaemon(boolean)
-	 */
-	public void test_setDaemonZ() {
-		// Test for method void java.lang.ThreadGroup.setDaemon(boolean)
-
-		daemonTests();
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#setMaxPriority(int)
-	 */
-	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);
-		}
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#stop()
-	 */
-	public void test_stop() throws OutOfMemoryError {
-		// Test for method void java.lang.ThreadGroup.stop()
-
-		final ThreadGroup originalCurrent = getInitialThreadGroup();
-
-		final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
-				"Test group");
-		final int DEPTH = 2;
-		buildRandomTreeUnder(testRoot, DEPTH);
-
-		final int THREADS_PER_GROUP = 2;
-		final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
-				THREADS_PER_GROUP);
-
-		try {
-			for (int i = 0; i < threads.size(); i++) {
-				Thread t = threads.elementAt(i);
-				t.start();
-			}
-		} catch (OutOfMemoryError e) {
-			for (int i = 0; i < threads.size(); i++) {
-				Thread t = threads.elementAt(i);
-				t.stop(); // deprecated but effective
-			}
-			throw e;
-		}
-
-		// Now that they are all running, let's stop the ThreadGroup
-		testRoot.stop();
-
-		// stop is an async call. The thread may take a while to stop. We have
-		// to wait for all of them to stop. However, if stop does not work,
-		// we'd have to wait forever. So, we wait with a timeout, and if the
-		// Thread is still alive, we assume stop for ThreadGroups does not
-		// work. How much we wait (timeout) is very important
-		boolean passed = true;
-		for (int i = 0; i < threads.size(); i++) {
-			Thread t = threads.elementAt(i);
-			try {
-				// We wait 5000 ms per Thread, but due to scheduling it may
-				// take a while to run
-				t.join(5000);
-			} catch (InterruptedException ie) {
-				fail("Should not be interrupted");
-			}
-			if (t.isAlive()) {
-				passed = false;
-				break;
-			}
-		}
-
-		// To make sure that even if we fail, we exit in a clean state
-		testRoot.destroy();
-
-		assertTrue("Thread should be dead by now", passed);
-
-		assertEquals("Method destroy (or wipeAllThreads) must have problems",
-				0, testRoot.activeCount());
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#suspend()
-	 */
-	public void test_suspend() throws OutOfMemoryError {
-		// Test for method void java.lang.ThreadGroup.suspend()
-
-		final ThreadGroup originalCurrent = getInitialThreadGroup();
-
-		final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
-				"Test group");
-		final int DEPTH = 2;
-		buildRandomTreeUnder(testRoot, DEPTH);
-
-		final int THREADS_PER_GROUP = 2;
-		final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
-				THREADS_PER_GROUP);
-
-		boolean passed = false;
-		try {
-			try {
-				for (int i = 0; i < threads.size(); i++) {
-					Thread t = threads.elementAt(i);
-					t.start();
-				}
-			} catch (OutOfMemoryError e) {
-				for (int i = 0; i < threads.size(); i++) {
-					Thread t = threads.elementAt(i);
-					t.stop(); // deprecated but effective
-				}
-				throw e;
-			}
-
-			// Now that they are all running, let's suspend the ThreadGroup
-			testRoot.suspend();
-
-			passed = allSuspended(threads);
-			assertTrue("Should be able to wipe all threads (allSuspended="
-					+ passed + ")", wipeAllThreads(testRoot));
-		} finally {
-
-			// We can't destroy a ThreadGroup if we do not make sure it has no
-			// threads at all
-
-			// Make sure we cleanup before returning from the method
-			testRoot.destroy();
-		}
-		assertTrue("All threads should be suspended", passed);
-
-		assertEquals("Method destroy (or wipeAllThreads) must have problems",
-				0, testRoot.activeCount());
-
-	}
-
-	/**
-	 * @tests java.lang.ThreadGroup#toString()
-	 */
-	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)
-	 */
-	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 {
-		}
-		;
-
-		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-		// - - - - - - -
-		testRoot = new ThreadGroup(originalCurrent,
-				"Test killing a Thread, forcing it to throw ThreadDeath") {
-			public void uncaughtException(Thread t, Throwable e) {
-				if (e instanceof ThreadDeath) {
-                    passed[TEST_KILLING] = true;
-                }
-				// always forward, any exception
-				super.uncaughtException(t, e);
-			}
-		};
-
-		// Test if a Thread tells its ThreadGroup about ThreadDeath
-		thread = new Thread(testRoot, null, "victim thread (to be killed)") {
-			public void run() {
-				while (true) {
-					Thread.yield();
-				}
-			}
-		};
-		thread.start();
-		try {
-			Thread.sleep(1000);
-		} catch (InterruptedException ie) {
-			fail("Should not have been interrupted");
-		}
-		// we know this is deprecated, but we must test this scenario.
-		// When we stop a thread, it is tagged as not alive even though it is
-		// still running code.
-		// join would be a no-op, and we might have a race condition. So, to
-		// play safe, we wait before joining & testing if the exception was
-		// really forwarded to the ThreadGroup
-		thread.stop();
-		try {
-			Thread.sleep(1000);
-		} catch (InterruptedException ie) {
-			fail("Should not have been interrupted");
-		}
-		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 killed:"
-						+ testRoot, passed[TEST_KILLING]);
-
-		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-		// - - - - - - -
-		testRoot = new ThreadGroup(originalCurrent,
-				"Test Forcing a throw of ThreadDeath") {
-			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") {
-			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") {
-			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") {
-			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") {
-			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 {
-		}
-		;
-
-		testRoot = new ThreadGroup(originalCurrent,
-				"Test Exception in uncaught exception") {
-			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();
-				} else {
-                    // 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") {
-			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") {
-			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") {
-			public void run() {
-				throw new TestException();
-			}
-		};
-		thread.start();
-		try {
-			thread.join();
-		} catch (InterruptedException ie) {
-			fail("Should not have been interrupted");
-		}
-		testRoot.destroy();
-	}
-
-	@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 wipeAllThreads(final Vector<?> threads) {
-		boolean ok = true;
-		for (int i = 0; i < threads.size(); i++) {
-			Thread t = (Thread) threads.elementAt(i);
-			ok = ok && wipeThread(t);
-		}
-
-		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().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) {
-				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 verifyThreadList(ThreadGroup root,
-			ThreadGroup onlyChildGroup, byte[] listOutput) {
-		// We expect that @root has only 1 subgroup, @onlyChildGroup. The
-		// output from  method 'list' is stored in @listOutput
-		if (listOutput.length == 0) {
-			return false;
-		}
-
-		// If we got a long output, it means some previous test must have left
-		// side-effects (more subgroups and threads);
-		final int MAX_SIZE = 200;
-		if (listOutput.length > MAX_SIZE) {
-			return false;
-		}
-
-		// Here we compare actual result to expected result
-
-		// Due to extremely weak API in String, comparing substrings, etc would
-		// take too much work at this time.
-		// We defer the actual implementation for now.
-		return true;
-	}
-
-	private boolean allNotSuspended(Vector<?> threads) {
-		for (int i = 0; i < threads.size(); i++) {
-			MyThread t = (MyThread) threads.elementAt(i);
-			if (!t.isActivelyRunning()) {
-                return false;
-            }
-		}
-
-		return true;
-
-	}
-
-	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 boolean sameThreads(Thread[] allThreads, Vector<?> threads) {
-		if (allThreads.length != threads.size()) {
-            return false;
-        }
-
-		// The complexity of this method is N2, and we do it twice !!
-
-		// First make sure that all threads in @threads are also in @allThreads
-		for (int i = 0; i < allThreads.length; i++) {
-			Thread t = (Thread) threads.elementAt(i);
-			if (!arrayIncludes(allThreads, t)) {
-                return false;
-            }
-		}
-
-		// Now make sure that all threads in @allThreads are also in @threads
-		Thread[] vectorThreads = new Thread[threads.size()];
-		threads.copyInto(vectorThreads);
-		for (int i = 0; i < vectorThreads.length; i++) {
-			Thread t = allThreads[i];
-			if (!arrayIncludes(vectorThreads, t)) {
-                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);
-
-	}
-
-	private boolean parentOfAll(ThreadGroup parentCandidate,
-			ThreadGroup[] childrenCandidates) {
-		for (ThreadGroup element : childrenCandidates) {
-			if (!parentCandidate.parentOf(element)) {
-                return false;
-            }
-		}
-
-		return true;
-
-	}
-
-	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;
-
-	}
-}
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.luni.tests.java.lang;
+
+import java.util.Vector;
+
+public class ThreadGroupTest extends junit.framework.TestCase {
+
+	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) {
+				}
+			}
+		}
+
+		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)
+	 */
+	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();
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.ThreadGroup,
+	 *        java.lang.String)
+	 */
+	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);
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#activeCount()
+	 */
+	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 count = tg.activeCount();
+		assertTrue("wrong active count: " + count, count == 0);
+		t1.start();
+		count = tg.activeCount();
+		assertTrue("wrong active count: " + count, count == 1);
+		t1.interrupt();
+		try {
+			t1.join();
+		} catch (InterruptedException e) {
+		}
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#checkAccess()
+	 */
+	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();
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#destroy()
+	 */
+	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);
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#destroy()
+	 */
+	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()
+	 */
+	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;
+		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()
+	 */
+	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()
+	 */
+	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#isDaemon()
+	 */
+	public void test_isDaemon() {
+		// Test for method boolean java.lang.ThreadGroup.isDaemon()
+
+		daemonTests();
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#list()
+	 */
+	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) {
+            System.out.println("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();
+			byte[] contents = contentsStream.toByteArray();
+
+			/*
+			 * 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]
+			 * 
+			 */
+
+			boolean passed = verifyThreadList(originalCurrent, testRoot,
+					contents);
+
+			assertTrue(
+					"Either 'list' is wrong or other tests are leaving side-effects.\n"
+							+ "Result from list:\n " + "-----------------\n "
+							+ new String(contents, 0, contents.length)
+							+ "\n-----------------\n ", 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)
+	 */
+	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()
+	 */
+	@SuppressWarnings("deprecation")
+    public void test_resume() throws OutOfMemoryError {
+		// Test for method void java.lang.ThreadGroup.resume()
+
+		final ThreadGroup originalCurrent = getInitialThreadGroup();
+
+		final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
+				"Test group");
+		final int DEPTH = 2;
+		buildRandomTreeUnder(testRoot, DEPTH);
+
+		final int THREADS_PER_GROUP = 2;
+		final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
+				THREADS_PER_GROUP);
+
+		boolean[] isResumed = null;
+		try {
+			try {
+				for (int i = 0; i < threads.size(); i++) {
+					Thread t = threads.elementAt(i);
+					t.start();
+					t.suspend();
+				}
+				// In 5.0, activeCount() only returns threads that are alive
+				assertTrue("Internal error when populating ThreadGroups", testRoot
+						.activeCount() == threads.size());
+			} catch (OutOfMemoryError e) {
+				for (int i = 0; i < threads.size(); i++) {
+					Thread t = threads.elementAt(i);
+					t.resume();
+					t.stop(); // deprecated but effective
+				}
+				throw e;
+			}
+
+			// Now that they are all suspended, let's resume the ThreadGroup
+			testRoot.resume();
+
+			// Give them some time to really resume
+			try {
+				Thread.sleep(500);
+			} catch (InterruptedException ie) {
+				fail("Should not have been interrupted");
+			}
+
+			isResumed = new boolean[threads.size()];
+			boolean failed = false;
+			for (int i = 0; i < isResumed.length; i++) {
+				MyThread t = threads.elementAt(i);
+				if (!failed) { // if one failed, don't waste time checking the
+					// rest
+					isResumed[i] = t.isActivelyRunning(1000);
+					failed = failed | (!isResumed[i]);
+				}
+				t.stop(); // deprecated but effective
+			}
+
+			// Give them some time to really die
+			try {
+				Thread.sleep(500);
+			} catch (InterruptedException ie) {
+				fail("Should not have been interrupted");
+			}
+		} finally {
+			// Make sure we do cleanup before returning
+			testRoot.destroy();
+		}
+
+		for (int i = 0; i < isResumed.length; i++) {
+			assertTrue("Thread " + threads.elementAt(i)
+					+ " was not running when it was killed", isResumed[i]);
+		}
+
+		assertEquals("Method destroy must have problems",
+				0, testRoot.activeCount());
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#setDaemon(boolean)
+	 */
+	public void test_setDaemonZ() {
+		// Test for method void java.lang.ThreadGroup.setDaemon(boolean)
+
+		daemonTests();
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#setMaxPriority(int)
+	 */
+	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);
+		}
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#stop()
+	 */
+	public void test_stop() throws OutOfMemoryError {
+		// Test for method void java.lang.ThreadGroup.stop()
+
+		final ThreadGroup originalCurrent = getInitialThreadGroup();
+
+		final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
+				"Test group");
+		final int DEPTH = 2;
+		buildRandomTreeUnder(testRoot, DEPTH);
+
+		final int THREADS_PER_GROUP = 2;
+		final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
+				THREADS_PER_GROUP);
+
+		try {
+			for (int i = 0; i < threads.size(); i++) {
+				Thread t = threads.elementAt(i);
+				t.start();
+			}
+		} catch (OutOfMemoryError e) {
+			for (int i = 0; i < threads.size(); i++) {
+				Thread t = threads.elementAt(i);
+				t.stop(); // deprecated but effective
+			}
+			throw e;
+		}
+
+		// Now that they are all running, let's stop the ThreadGroup
+		testRoot.stop();
+
+		// stop is an async call. The thread may take a while to stop. We have
+		// to wait for all of them to stop. However, if stop does not work,
+		// we'd have to wait forever. So, we wait with a timeout, and if the
+		// Thread is still alive, we assume stop for ThreadGroups does not
+		// work. How much we wait (timeout) is very important
+		boolean passed = true;
+		for (int i = 0; i < threads.size(); i++) {
+			Thread t = threads.elementAt(i);
+			try {
+				// We wait 5000 ms per Thread, but due to scheduling it may
+				// take a while to run
+				t.join(5000);
+			} catch (InterruptedException ie) {
+				fail("Should not be interrupted");
+			}
+			if (t.isAlive()) {
+				passed = false;
+				break;
+			}
+		}
+
+		// To make sure that even if we fail, we exit in a clean state
+		testRoot.destroy();
+
+		assertTrue("Thread should be dead by now", passed);
+
+		assertEquals("Method destroy (or wipeAllThreads) must have problems",
+				0, testRoot.activeCount());
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#suspend()
+	 */
+	public void test_suspend() throws OutOfMemoryError {
+		// Test for method void java.lang.ThreadGroup.suspend()
+
+		final ThreadGroup originalCurrent = getInitialThreadGroup();
+
+		final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
+				"Test group");
+		final int DEPTH = 2;
+		buildRandomTreeUnder(testRoot, DEPTH);
+
+		final int THREADS_PER_GROUP = 2;
+		final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
+				THREADS_PER_GROUP);
+
+		boolean passed = false;
+		try {
+			try {
+				for (int i = 0; i < threads.size(); i++) {
+					Thread t = threads.elementAt(i);
+					t.start();
+				}
+			} catch (OutOfMemoryError e) {
+				for (int i = 0; i < threads.size(); i++) {
+					Thread t = threads.elementAt(i);
+					t.stop(); // deprecated but effective
+				}
+				throw e;
+			}
+
+			// Now that they are all running, let's suspend the ThreadGroup
+			testRoot.suspend();
+
+			passed = allSuspended(threads);
+			assertTrue("Should be able to wipe all threads (allSuspended="
+					+ passed + ")", wipeAllThreads(testRoot));
+		} finally {
+
+			// We can't destroy a ThreadGroup if we do not make sure it has no
+			// threads at all
+
+			// Make sure we cleanup before returning from the method
+			testRoot.destroy();
+		}
+		assertTrue("All threads should be suspended", passed);
+
+		assertEquals("Method destroy (or wipeAllThreads) must have problems",
+				0, testRoot.activeCount());
+
+	}
+
+	/**
+	 * @tests java.lang.ThreadGroup#toString()
+	 */
+	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)
+	 */
+	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 {
+		}
+		;
+
+		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+		// - - - - - - -
+		testRoot = new ThreadGroup(originalCurrent,
+				"Test killing a Thread, forcing it to throw ThreadDeath") {
+			public void uncaughtException(Thread t, Throwable e) {
+				if (e instanceof ThreadDeath) {
+                    passed[TEST_KILLING] = true;
+                }
+				// always forward, any exception
+				super.uncaughtException(t, e);
+			}
+		};
+
+		// Test if a Thread tells its ThreadGroup about ThreadDeath
+		thread = new Thread(testRoot, null, "victim thread (to be killed)") {
+			public void run() {
+				while (true) {
+					Thread.yield();
+				}
+			}
+		};
+		thread.start();
+		try {
+			Thread.sleep(1000);
+		} catch (InterruptedException ie) {
+			fail("Should not have been interrupted");
+		}
+		// we know this is deprecated, but we must test this scenario.
+		// When we stop a thread, it is tagged as not alive even though it is
+		// still running code.
+		// join would be a no-op, and we might have a race condition. So, to
+		// play safe, we wait before joining & testing if the exception was
+		// really forwarded to the ThreadGroup
+		thread.stop();
+		try {
+			Thread.sleep(1000);
+		} catch (InterruptedException ie) {
+			fail("Should not have been interrupted");
+		}
+		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 killed:"
+						+ testRoot, passed[TEST_KILLING]);
+
+		// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+		// - - - - - - -
+		testRoot = new ThreadGroup(originalCurrent,
+				"Test Forcing a throw of ThreadDeath") {
+			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") {
+			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") {
+			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") {
+			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") {
+			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 {
+		}
+		;
+
+		testRoot = new ThreadGroup(originalCurrent,
+				"Test Exception in uncaught exception") {
+			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();
+				} else {
+                    // 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") {
+			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") {
+			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") {
+			public void run() {
+				throw new TestException();
+			}
+		};
+		thread.start();
+		try {
+			thread.join();
+		} catch (InterruptedException ie) {
+			fail("Should not have been interrupted");
+		}
+		testRoot.destroy();
+	}
+
+	@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 wipeAllThreads(final Vector<?> threads) {
+		boolean ok = true;
+		for (int i = 0; i < threads.size(); i++) {
+			Thread t = (Thread) threads.elementAt(i);
+			ok = ok && wipeThread(t);
+		}
+
+		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().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) {
+				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 verifyThreadList(ThreadGroup root,
+			ThreadGroup onlyChildGroup, byte[] listOutput) {
+		// We expect that @root has only 1 subgroup, @onlyChildGroup. The
+		// output from  method 'list' is stored in @listOutput
+		if (listOutput.length == 0) {
+			return false;
+		}
+
+		// If we got a long output, it means some previous test must have left
+		// side-effects (more subgroups and threads);
+		final int MAX_SIZE = 200;
+		if (listOutput.length > MAX_SIZE) {
+			return false;
+		}
+
+		// Here we compare actual result to expected result
+
+		// Due to extremely weak API in String, comparing substrings, etc would
+		// take too much work at this time.
+		// We defer the actual implementation for now.
+		return true;
+	}
+
+	private boolean allNotSuspended(Vector<?> threads) {
+		for (int i = 0; i < threads.size(); i++) {
+			MyThread t = (MyThread) threads.elementAt(i);
+			if (!t.isActivelyRunning()) {
+                return false;
+            }
+		}
+
+		return true;
+
+	}
+
+	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 boolean sameThreads(Thread[] allThreads, Vector<?> threads) {
+		if (allThreads.length != threads.size()) {
+            return false;
+        }
+
+		// The complexity of this method is N2, and we do it twice !!
+
+		// First make sure that all threads in @threads are also in @allThreads
+		for (int i = 0; i < allThreads.length; i++) {
+			Thread t = (Thread) threads.elementAt(i);
+			if (!arrayIncludes(allThreads, t)) {
+                return false;
+            }
+		}
+
+		// Now make sure that all threads in @allThreads are also in @threads
+		Thread[] vectorThreads = new Thread[threads.size()];
+		threads.copyInto(vectorThreads);
+		for (int i = 0; i < vectorThreads.length; i++) {
+			Thread t = allThreads[i];
+			if (!arrayIncludes(vectorThreads, t)) {
+                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);
+		}
+

[... 88 lines stripped ...]