| /* |
| * 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. |
| */ |
| |
| /** |
| * @author Roman S. Bushmanov |
| */ |
| |
| package java.lang; |
| |
| import junit.framework.TestCase; |
| import java.io.*; |
| |
| import org.apache.harmony.test.ReversibleSecurityManager; |
| |
| public class ThreadGroupTest extends TestCase { |
| |
| private static final String INTERRUPTED_MESSAGE = |
| "thread has been unexpectedly interrupted"; |
| |
| // max time interval to wait for some events in ms |
| private static final long waitDuration = 3000; |
| |
| // waiting time for some event |
| private static long waitTime = 0; |
| private boolean expired; |
| private static PrintStream systemOut = System.out; |
| private static PrintStream systemErr = System.err; |
| |
| class ExceptionHandler implements Thread.UncaughtExceptionHandler { |
| |
| public boolean wasCalled = false; |
| |
| public void uncaughtException(Thread t, Throwable e) { |
| wasCalled = true; |
| } |
| } |
| |
| class ThreadGroupHandler extends ThreadGroup { |
| boolean handlerWasCalled = false; |
| |
| public ThreadGroupHandler(String name) { |
| super(name); |
| } |
| |
| public ThreadGroupHandler(ThreadGroup g, String name) { |
| super(g, name); |
| } |
| |
| public void uncaughtException(Thread t, Throwable e) { |
| handlerWasCalled = true; |
| } |
| } |
| |
| class TestThread extends Thread { |
| |
| volatile boolean enough = false; |
| |
| boolean finished = false; |
| |
| TestThread(ThreadGroup group, String name) { |
| super(group, name); |
| } |
| |
| public void run() { |
| while (!enough) { |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| } |
| } |
| finished = true; |
| } |
| } |
| |
| /** |
| * Sleep for "interval" ms |
| * @return true if waitTime is up |
| */ |
| private static boolean doSleep(int interval) { |
| try { |
| Thread.sleep(interval); |
| } catch (InterruptedException e) { |
| fail("unexpected InterruptedException while sleeping"); |
| } |
| waitTime -= interval; |
| return waitTime <= 0; |
| } |
| |
| /** |
| * ThreadGroup(String) |
| */ |
| public void testThreadGroupThreadGroupString() { |
| ThreadGroup group = new ThreadGroup("group"); |
| assertSame("wrong parrent", |
| Thread.currentThread().getThreadGroup(), group.getParent()); |
| } |
| |
| /** |
| * Create a ThreadGroup in a destroyed ThreadGroup |
| */ |
| public void testThreadGroupThreadGroupString_InDestroyedGroup() { |
| try { |
| ThreadGroup group = new ThreadGroup("group"); |
| group.destroy(); |
| new ThreadGroup(group, "group1"); |
| fail("Constructor should throw IllegalThreadStateException!"); |
| } catch (IllegalThreadStateException e) { |
| return; |
| } |
| } |
| |
| /** |
| * test ThreadGroup(null) |
| */ |
| public void testThreadGroupString_Null() { |
| ThreadGroup group = null; |
| try { |
| group = new ThreadGroup(null); |
| } catch (NullPointerException e) { |
| fail("Constructor should accept null names!"); |
| } |
| assertNull(group.getName()); |
| } |
| |
| /** |
| * activeCount() in a new ThreadGroup |
| */ |
| public void testActiveCount_NoThreads() { |
| ThreadGroup group = new ThreadGroup("new"); |
| assertEquals(0, group.activeCount()); |
| } |
| |
| /** |
| * activeCount() in a ThreadGroup with an empty subgroup |
| */ |
| public void testActiveCount_CreateDestroySubgroup() { |
| ThreadGroup group = new ThreadGroup("group"); |
| ThreadGroup group1 = new ThreadGroup(group, "group1"); |
| assertEquals(1, group.activeGroupCount()); |
| group1.destroy(); |
| assertEquals(0, group.activeGroupCount()); |
| } |
| |
| /** |
| * activeCount() in a ThreadGroup with a few new threads |
| */ |
| public void testActiveCount_NewThreads() { |
| ThreadGroup group = new ThreadGroup("new"); |
| new Thread(group, "t1"); |
| new Thread(group, "t2"); |
| new Thread(group, "t3"); |
| assertEquals(0, group.activeCount()); |
| } |
| |
| /** |
| * activeCount() in a ThreadGroup with a few started and |
| * terminated threads |
| */ |
| public void testActiveCount_StartedTerminatedThreads() { |
| ThreadGroup group = new ThreadGroup("new"); |
| ThreadTest.ThreadRunning t1 = new ThreadTest.ThreadRunning(group, "t1"); |
| ThreadTest.ThreadRunning t2 = new ThreadTest.ThreadRunning(group, "t2"); |
| ThreadTest.ThreadRunning t3 = new ThreadTest.ThreadRunning(group, "t3"); |
| t1.start(); |
| t2.start(); |
| t3.start(); |
| doSleep(100); |
| assertEquals("incorrect number of started threads", |
| 3, group.activeCount()); |
| t1.stopWork = true; |
| t2.stopWork = true; |
| t3.stopWork = true; |
| try { |
| t1.join(); |
| t2.join(); |
| t3.join(); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| assertEquals("there should be no live threads", 0, group.activeCount()); |
| } |
| |
| /** |
| * activeCount() in a ThreadGroup with a few threads running in a subgroups |
| */ |
| public void testActiveCount_Subgroup() { |
| ThreadGroup parent = new ThreadGroup("parent"); |
| ThreadGroup child1 = new ThreadGroup(parent, "child1"); |
| ThreadTest.ThreadRunning t11 = new ThreadTest.ThreadRunning(parent, |
| "t11"); |
| ThreadTest.ThreadRunning tc11 = new ThreadTest.ThreadRunning(child1, |
| "tc11"); |
| ThreadTest.ThreadRunning tc12 = new ThreadTest.ThreadRunning(child1, |
| "tc12"); |
| ThreadGroup gChild1 = new ThreadGroup(child1, "gChild1"); |
| ThreadTest.ThreadRunning tgc11 = new ThreadTest.ThreadRunning(gChild1, |
| "tgc11"); |
| ThreadTest.ThreadRunning tgc12 = new ThreadTest.ThreadRunning(gChild1, |
| "tgc12"); |
| ThreadGroup child2 = new ThreadGroup(parent, "child2"); |
| ThreadTest.ThreadRunning tc21 = new ThreadTest.ThreadRunning(child2, |
| "tc21"); |
| ThreadTest.ThreadRunning tc22 = new ThreadTest.ThreadRunning(child2, |
| "tc22"); |
| assertEquals("new threads should not be counted", |
| 0, parent.activeCount()); |
| t11.start(); |
| tc11.start(); |
| tc12.start(); |
| tgc11.start(); |
| tgc12.start(); |
| tc21.start(); |
| tc22.start(); |
| doSleep(100); |
| assertEquals("incorrect number of active threads", |
| 7, parent.activeCount()); |
| t11.stopWork = true; |
| tc11.stopWork = true; |
| tc12.stopWork = true; |
| tgc11.stopWork = true; |
| tgc12.stopWork = true; |
| tc21.stopWork = true; |
| tc22.stopWork = true; |
| try { |
| t11.join(); |
| tc11.join(); |
| tc12.join(); |
| tgc11.join(); |
| tgc12.join(); |
| tc21.join(); |
| tc22.join(); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| assertEquals("there should be no live threads", 0, parent.activeCount()); |
| } |
| |
| /** |
| * Verify activeGroupCount() for a group containing |
| * a few subgroups |
| */ |
| public void testActiveGroupCount_Subgroups() { |
| ThreadGroup tg1 = new ThreadGroup("group 1"); |
| new ThreadGroup(tg1, "group 11"); |
| ThreadGroup tg12 = new ThreadGroup(tg1, "group 12"); |
| new ThreadGroup(tg1, "group 13"); |
| new ThreadGroup(tg12, "group 121"); |
| new ThreadGroup(tg12, "group 122"); |
| ThreadGroup tg123 = new ThreadGroup(tg12, "group 123"); |
| new Thread(tg123, "thread 1231"); |
| new Thread(tg123, "thread 1232"); |
| assertEquals(6, tg1.activeGroupCount()); |
| } |
| |
| /** |
| * Verify activeGroupCount() after destroying a group |
| * where one of subgroups is not empty |
| */ |
| public void testActiveGroupCount_DestroyNonEmptySubgroup() { |
| ThreadGroup tg1 = new ThreadGroup("group 1"); |
| ThreadGroup tg11 = new ThreadGroup(tg1, "group 11"); |
| ThreadGroup tg12 = new ThreadGroup(tg1, "group 12"); |
| ThreadGroup tg13 = new ThreadGroup(tg1, "group 13"); |
| ThreadGroup tg121 = new ThreadGroup(tg12, "group 121"); |
| ThreadGroup tg122 = new ThreadGroup(tg12, "group 122"); |
| ThreadGroup tg123 = new ThreadGroup(tg12, "group 123"); |
| new ThreadTest.ThreadRunning(tg122, "thread 1221").start(); |
| new ThreadTest.ThreadRunning(tg122, "thread 1222").start(); |
| // Non-empty subgroup tg122 should not be destroyed. |
| // IllegalThreadStateException should be thrown. |
| // Groups residing on the right from tg123 in the groups tree |
| // should not be destroyed as well. |
| try { |
| tg1.destroy(); |
| fail("IllegalThreadStateException has not been thrown when " + |
| "destroying non-empty subgroup"); |
| } catch (IllegalThreadStateException e) { |
| } |
| assertEquals("wrong group count in tg1", 0, tg1.activeGroupCount()); |
| assertEquals("wrong group count in tg12", 0, tg12.activeGroupCount()); |
| assertTrue("tg1 is not destroyed", tg1.isDestroyed()); |
| assertTrue("tg11 is not destroyed", tg11.isDestroyed()); |
| assertTrue("tg12 is not destroyed", tg12.isDestroyed()); |
| assertTrue("tg13 is destroyed", !tg13.isDestroyed()); |
| assertTrue("tg121 is not destroyed", tg121.isDestroyed()); |
| assertTrue("tg122 is destroyed", !tg122.isDestroyed()); |
| assertTrue("tg123 is destroyed", !tg123.isDestroyed()); |
| } |
| |
| /** |
| * Verify the checkAccess() method |
| */ |
| public void testCheckAccess() { |
| SecurityManager sm = System.getSecurityManager(); |
| System.setSecurityManager(new ReversibleSecurityManager()); |
| ThreadGroup tg1 = new ThreadGroup("tg1"); |
| try { |
| tg1.checkAccess(); |
| } finally { |
| System.setSecurityManager(sm); |
| } |
| } |
| |
| /** |
| * Checks the destroy() method for a destroyed thread group. |
| * IllegalThreadStateException should be thrown. |
| */ |
| public void testDestroy_Destroyed() { |
| ThreadGroup tg1 = new ThreadGroup("tg1"); |
| ThreadGroup tg2 = new ThreadGroup(tg1, "tg2"); |
| tg2.setDaemon(true); |
| TestThread t2 = new TestThread(tg2, "t2"); |
| t2.start(); |
| t2.enough = true; |
| try { |
| t2.join(); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| // tg2 is daemon and should be already destroyed |
| try { |
| tg2.destroy(); |
| fail("IllegalThreadStateException should be thrown " + |
| "when destroying a destroyed thread group"); |
| } catch (IllegalThreadStateException e) { |
| } |
| } |
| |
| /** |
| * Checks the destroy() method for a group containing a destroyed subgroup. |
| * IllegalThreadStateException should not be thrown. |
| */ |
| public void testDestroy_DestroyedSubgroup() { |
| ThreadGroup tg1 = new ThreadGroup("tg1"); |
| ThreadGroup tg2 = new ThreadGroup(tg1, "tg2"); |
| tg2.setDaemon(true); |
| TestThread t2 = new TestThread(tg2, "t2"); |
| t2.start(); |
| t2.enough = true; |
| try { |
| t2.join(); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| |
| // tg1 should be destroyed because its subgroup tg2 has been destroyed |
| // silently as a daemon ThreadGroup with no live threads |
| try { |
| tg1.destroy(); |
| } catch (IllegalThreadStateException e) { |
| fail("IllegalThreadStateException has been thrown when destroying" + |
| " a thread group containing a destroyed subgroup"); |
| } |
| } |
| |
| /** |
| * Verify destroying a group where one of subgroups is not empty |
| * but all threads in it have finished. |
| */ |
| public void testDestroy_FinishedThreads() { |
| ThreadGroup tg1 = new ThreadGroup("group 1"); |
| ThreadGroup tg11 = new ThreadGroup(tg1, "group 11"); |
| ThreadGroup tg12 = new ThreadGroup(tg1, "group 12"); |
| ThreadGroup tg13 = new ThreadGroup(tg1, "group 13"); |
| ThreadGroup tg121 = new ThreadGroup(tg12, "group 121"); |
| ThreadGroup tg122 = new ThreadGroup(tg12, "group 122"); |
| ThreadGroup tg123 = new ThreadGroup(tg12, "group 123"); |
| ThreadTest.ThreadRunning t1 = new ThreadTest.ThreadRunning(tg123, |
| "thread 1231"); |
| t1.start(); |
| ThreadTest.ThreadRunning t2 = new ThreadTest.ThreadRunning(tg123, |
| "thread 1232"); |
| t2.start(); |
| t1.stopWork = true; |
| t2.stopWork = true; |
| try { |
| t1.join(); |
| t2.join(); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| for (waitTime = waitDuration; t1.isAlive() && t2.isAlive() && !(expired = doSleep(10));) { |
| } |
| if (expired) { |
| fail("thread have not finished for " + waitDuration + " ms"); |
| } |
| try { |
| tg1.destroy(); |
| } catch (IllegalThreadStateException e) { |
| fail("IllegalThreadStateException should not been thrown " + |
| "because threads have fnished"); |
| } |
| assertTrue(tg1.getName() + " has not been destroyed", tg1.isDestroyed()); |
| assertTrue(tg11.getName() + " has not been destroyed", tg11.isDestroyed()); |
| assertTrue(tg12.getName() + " has not been destroyed", tg12.isDestroyed()); |
| assertTrue(tg13.getName() + " has not been destroyed", tg13.isDestroyed()); |
| assertTrue(tg121.getName() + " has not been destroyed", tg121.isDestroyed()); |
| assertTrue(tg122.getName() + " has not been destroyed", tg122.isDestroyed()); |
| assertTrue(tg123.getName() + " has not been destroyed", tg123.isDestroyed()); |
| assertEquals("tg1 should be empty", 0, tg1.activeGroupCount()); |
| assertEquals("tg12 should be empty", 0, tg12.activeGroupCount()); |
| } |
| |
| /** |
| * Checks the destroy() method for a group with 3 subgroups. |
| * Verifies the <code>destroyed</code> flag. |
| */ |
| public void testDestroy_ThreeChildren() { |
| ThreadGroup groups[] = {new ThreadGroup("tg0"), null, null, null}; |
| groups[1] = new ThreadGroup(groups[0], "tg1"); |
| groups[2] = new ThreadGroup(groups[0], "tg2"); |
| groups[3] = new ThreadGroup(groups[0], "tg3"); |
| groups[0].destroy(); |
| assertTrue("group[0] has not been destroyed", groups[0].isDestroyed()); |
| assertTrue("group[1] has not been destroyed", groups[1].isDestroyed()); |
| assertTrue("group[2] has not been destroyed", groups[2].isDestroyed()); |
| assertTrue("group[3] has not been destroyed", groups[3].isDestroyed()); |
| } |
| |
| /** |
| * Checks the destroy() method for a group with 2 subgroups. |
| * Verifies the activeGroupCount() value. |
| */ |
| public void testDestroy_TwoChildren() { |
| ThreadGroup group = new ThreadGroup("group"); |
| new ThreadGroup(group, "group1"); |
| new ThreadGroup(group, "group2"); |
| assertEquals(2, group.activeGroupCount()); |
| group.destroy(); |
| assertEquals(0, group.activeGroupCount()); |
| } |
| |
| /** |
| * Verify getMaxPriority() |
| */ |
| public void testGetMaxPriority() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| int groupMaxPriority = tg.getMaxPriority(); |
| assertEquals("incorrect priority", |
| Thread.currentThread().getThreadGroup().getMaxPriority(), |
| groupMaxPriority); |
| Thread t = new Thread(tg, "t"); |
| assertTrue("incorect thread's priority", |
| t.getPriority() <= groupMaxPriority); |
| } |
| |
| /** |
| * Verify enumerate(Thread[]) |
| */ |
| public void testEnumerateThread() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| ThreadGroup tg1 = new ThreadGroup(tg, "tg1"); |
| ThreadGroup tg2 = new ThreadGroup(tg1, "tg2"); |
| ThreadTest.ThreadRunning tArray[] = new ThreadTest.ThreadRunning[9]; |
| for (int i = 0; i < 3; i++) { |
| tArray[i] = new ThreadTest.ThreadRunning(tg, "ttt"); |
| tArray[i].start(); |
| tArray[i + 3] = new ThreadTest.ThreadRunning(tg1, "ttt"); |
| tArray[i + 3].start(); |
| tArray[i + 6] = new ThreadTest.ThreadRunning(tg2, "ttt"); |
| tArray[i + 6].start(); |
| } |
| doSleep(50); |
| // estimate dimension as 9 threads + 1 |
| int estimateLength = 10; |
| Thread list[]; |
| int count; |
| while (true) { |
| list = new Thread[estimateLength]; |
| count = tg.enumerate(list); |
| if (count == estimateLength) { |
| estimateLength *= 2; |
| } else { |
| break; |
| } |
| } |
| int enumerateCount = 0; |
| for (int i = 0; i < count; i++) { |
| if (list[i].toString().indexOf("ttt") > 0) { |
| enumerateCount++; |
| } |
| } |
| for (int i = 0; i < 9; i++) { |
| tArray[i].stopWork = true; |
| } |
| assertEquals("incorrect number of threads in tg", 9, enumerateCount); |
| } |
| |
| /** |
| * Verify enumerate(Thread[], false) |
| */ |
| public void testEnumerateThreadBoolean_False() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| ThreadGroup tg1 = new ThreadGroup(tg, "tg1"); |
| ThreadGroup tg2 = new ThreadGroup(tg1, "tg2"); |
| ThreadTest.ThreadRunning tArray[] = new ThreadTest.ThreadRunning[9]; |
| for (int i = 0; i < 3; i++) { |
| tArray[i] = new ThreadTest.ThreadRunning(tg, "ttt"); |
| tArray[i].start(); |
| tArray[i + 3] = new ThreadTest.ThreadRunning(tg1, "ttt"); |
| tArray[i + 3].start(); |
| tArray[i + 6] = new ThreadTest.ThreadRunning(tg2, "ttt"); |
| tArray[i + 6].start(); |
| } |
| doSleep(50); |
| // estimate dimension as 3 threads + 1 |
| int estimateLength = 4; |
| Thread list[]; |
| int count; |
| while (true) { |
| list = new Thread[estimateLength]; |
| count = tg.enumerate(list, false); |
| if (count == estimateLength) { |
| estimateLength *= 2; |
| } else { |
| break; |
| } |
| } |
| int enumerateCount = 0; |
| for (int i = 0; i < count; i++) { |
| if (list[i].toString().indexOf("ttt") > 0) { |
| enumerateCount++; |
| } |
| } |
| for (int i = 0; i < 9; i++) { |
| tArray[i].stopWork = true; |
| } |
| assertEquals("incorrect number of threads in tg", 3, enumerateCount); |
| } |
| |
| /** |
| * Verify enumerate(Thread[], true) |
| */ |
| public void testEnumerateThread_True() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| ThreadGroup tg1 = new ThreadGroup(tg, "tg1"); |
| ThreadGroup tg2 = new ThreadGroup(tg1, "tg2"); |
| ThreadTest.ThreadRunning tArray[] = new ThreadTest.ThreadRunning[9]; |
| for (int i = 0; i < 3; i++) { |
| tArray[i] = new ThreadTest.ThreadRunning(tg, "ttt"); |
| tArray[i].start(); |
| tArray[i + 3] = new ThreadTest.ThreadRunning(tg1, "ttt"); |
| tArray[i + 3].start(); |
| tArray[i + 6] = new ThreadTest.ThreadRunning(tg2, "ttt"); |
| tArray[i + 6].start(); |
| } |
| doSleep(50); |
| // estimate dimension as 9 threads + 1 |
| int estimateLength = 10; |
| Thread list[]; |
| int count; |
| while (true) { |
| list = new Thread[estimateLength]; |
| count = tg.enumerate(list, true); |
| if (count == estimateLength) { |
| estimateLength *= 2; |
| } else { |
| break; |
| } |
| } |
| int enumerateCount = 0; |
| for (int i = 0; i < count; i++) { |
| if (list[i].toString().indexOf("ttt") > 0) { |
| enumerateCount++; |
| } |
| } |
| for (int i = 0; i < 9; i++) { |
| tArray[i].stopWork = true; |
| } |
| assertEquals("incorrect number of threads in tg", 9, enumerateCount); |
| } |
| |
| /** |
| * Verify enumerate(ThreadGroup[]) |
| */ |
| public void testEnumerateThreadGroup() { |
| ThreadGroup tg1 = new ThreadGroup("tg1"); |
| ThreadGroup tg11 = new ThreadGroup(tg1, "tg11"); |
| new ThreadGroup(tg1, "tg12"); |
| new ThreadGroup(tg11, "tg111"); |
| new ThreadGroup(tg11, "tg112"); |
| // estimate dimension as 4 threads + 1 |
| int estimateLength = 5; |
| ThreadGroup list[]; |
| int count; |
| while (true) { |
| list = new ThreadGroup[estimateLength]; |
| count = tg1.enumerate(list); |
| if (count == estimateLength) { |
| estimateLength *= 2; |
| } else { |
| break; |
| } |
| } |
| int enumerateCount = 0; |
| for (int i = 0; i < count; i++) { |
| if (list[i].toString().indexOf("tg1") > 0) { |
| enumerateCount++; |
| } |
| } |
| assertEquals("incorrect number of thread groups in tg", |
| 4, enumerateCount); |
| } |
| |
| /** |
| * Verify enumerate(ThreadGroup[]) when there is a destroyed subgroup |
| */ |
| public void testEnumerateThreadGroup_Destroyed() { |
| ThreadGroup tg1 = new ThreadGroup("tg1"); |
| ThreadGroup tg11 = new ThreadGroup(tg1, "tg11"); |
| new ThreadGroup(tg1, "tg12"); |
| ThreadGroup tg111 = new ThreadGroup(tg11, "tg111"); |
| new ThreadGroup(tg11, "tg112"); |
| tg111.destroy(); |
| // estimate dimension as 4 threads + 1 |
| int estimateLength = 5; |
| ThreadGroup list[]; |
| int count; |
| while (true) { |
| list = new ThreadGroup[estimateLength]; |
| count = tg1.enumerate(list); |
| if (count == estimateLength) { |
| estimateLength *= 2; |
| } else { |
| break; |
| } |
| } |
| int enumerateCount = 0; |
| for (int i = 0; i < count; i++) { |
| if (list[i].toString().indexOf("tg1") > 0) { |
| enumerateCount++; |
| } |
| } |
| assertEquals("incorrect number of thread groups in tg", |
| 3, enumerateCount); |
| } |
| |
| /** |
| * Verify enumerate(ThreadGroup[], false) |
| */ |
| public void testEnumerateThreadGroup_False() { |
| ThreadGroup tg1 = new ThreadGroup("tg1"); |
| ThreadGroup tg11 = new ThreadGroup(tg1, "tg11"); |
| new ThreadGroup(tg1, "tg12"); |
| new ThreadGroup(tg11, "tg111"); |
| new ThreadGroup(tg11, "tg112"); |
| // estimate dimension as 4 threads + 1 |
| int estimateLength = 5; |
| ThreadGroup list[]; |
| int count; |
| while (true) { |
| list = new ThreadGroup[estimateLength]; |
| count = tg1.enumerate(list, false); |
| if (count == estimateLength) { |
| estimateLength *= 2; |
| } else { |
| break; |
| } |
| } |
| int enumerateCount = 0; |
| for (int i = 0; i < count; i++) { |
| if (list[i].toString().indexOf("tg1") > 0) { |
| enumerateCount++; |
| } |
| } |
| assertEquals("incorrect number of thread groups in tg", |
| 2, enumerateCount); |
| } |
| |
| /** |
| * Verify enumerate(ThreadGroup[], true) |
| */ |
| public void testEnumerateThreadGroup_True() { |
| ThreadGroup tg1 = new ThreadGroup("tg1"); |
| ThreadGroup tg11 = new ThreadGroup(tg1, "tg11"); |
| new ThreadGroup(tg1, "tg12"); |
| new ThreadGroup(tg11, "tg111"); |
| new ThreadGroup(tg11, "tg112"); |
| // estimate dimension as 4 threads + 1 |
| int estimateLength = 5; |
| ThreadGroup list[]; |
| int count; |
| while (true) { |
| list = new ThreadGroup[estimateLength]; |
| count = tg1.enumerate(list, true); |
| if (count == estimateLength) { |
| estimateLength *= 2; |
| } else { |
| break; |
| } |
| } |
| int enumerateCount = 0; |
| for (int i = 0; i < count; i++) { |
| if (list[i].toString().indexOf("tg1") > 0) { |
| enumerateCount++; |
| } |
| } |
| assertEquals("incorrect number of thread groups in tg", |
| 4, enumerateCount); |
| } |
| |
| /** |
| * Verify getName() |
| */ |
| public void testGetName() { |
| String name = "newGroup"; |
| String childName = "newChildGroup"; |
| ThreadGroup tg = new ThreadGroup(name); |
| assertEquals("wrong name", name, tg.getName()); |
| ThreadGroup tgChild = new ThreadGroup(tg, childName); |
| assertEquals("wrong child name", childName, tgChild.getName()); |
| } |
| |
| /** |
| * Verify getParent() |
| */ |
| public void testGetParent() { |
| ThreadGroup parent = new ThreadGroup("parent"); |
| ThreadGroup child = new ThreadGroup(parent, "child"); |
| ThreadGroup grandChild = new ThreadGroup(child, "grandChild"); |
| assertSame("improper parent of child", parent, child.getParent()); |
| assertSame("improper parent of grandchild", |
| child, grandChild.getParent()); |
| } |
| |
| /** |
| * Verify getParent() of a destroyed group |
| */ |
| public void testGetParent_DestroyedGroup() { |
| ThreadGroup parent = new ThreadGroup("parent"); |
| ThreadGroup child = new ThreadGroup(parent, "child"); |
| ThreadGroup grandchild = new ThreadGroup(child, "grandchild"); |
| child.destroy(); |
| assertTrue("child has not been destroyed", child.isDestroyed()); |
| assertTrue("grandchild has not been destroyed", |
| grandchild.isDestroyed()); |
| assertSame("improper parent of a destroyed group", |
| parent, child.getParent()); |
| assertSame("a destroyed group should stay parent", |
| child, grandchild.getParent()); |
| } |
| |
| /** |
| * Verify getParent() of a top-level group |
| */ |
| public void testGetParent_TopLevelGroup() { |
| ThreadGroup parent = Thread.currentThread().getThreadGroup().getParent(); |
| int groupCount = 1000; |
| while ((parent != null) && (--groupCount >= 0)) { |
| parent = parent.getParent(); |
| } |
| assertNull("top-level group's parent is not null", parent); |
| } |
| |
| /** |
| * Interrupt a running thread |
| */ |
| public void testInterrupt() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| ThreadGroup tg1 = new ThreadGroup(tg, "tg1"); |
| ThreadTest.ThreadRunning tArray[] = new ThreadTest.ThreadRunning[6]; |
| for (int i = 0; i < 3; i++) { |
| tArray[i] = new ThreadTest.ThreadRunning(tg, "ttt"); |
| tArray[i].start(); |
| tArray[i + 3] = new ThreadTest.ThreadRunning(tg1, "ttt"); |
| tArray[i + 3].start(); |
| } |
| doSleep(50); |
| tg.interrupt(); |
| waitTime = waitDuration; |
| for (int i = 0; i < 6; i++) { |
| while (!tArray[i].isInterrupted() && !(expired = doSleep(10))) { |
| } |
| if (expired) { |
| break; |
| } |
| } |
| for (int i = 0; i < 6; i++) { |
| tArray[i].stopWork = true; |
| } |
| if (expired) { |
| fail("threads have not been interrupted"); |
| } |
| } |
| |
| /** |
| * Verify list() |
| */ |
| public void testList() { |
| File file = null; |
| PrintStream newOut = null; |
| try { |
| file = File.createTempFile("JUnit_ThreadGroupListTest", ".tmp"); |
| newOut = new PrintStream(new FileOutputStream(file)); |
| } catch (java.io.IOException e) { |
| fail("unexpected IOException 1: " + e); |
| } |
| try { |
| System.setOut(newOut); |
| } catch (SecurityException e) { |
| return; |
| } |
| ThreadGroup tg = new ThreadGroup("tg"); |
| tg.list(); |
| newOut.close(); |
| System.setOut(systemOut); |
| byte buf[] = new byte[100]; |
| try { |
| FileInputStream inp = new FileInputStream(file); |
| inp.read(buf); |
| inp.close(); |
| } catch (java.io.IOException e) { |
| fail("unexpected IOException 2: " + e); |
| } |
| file.delete(); |
| String toString = "java.lang.ThreadGroup[name=tg,maxpri="; |
| assertEquals("thread group info has not been printed", |
| 0, new String(buf).indexOf(toString)); |
| } |
| |
| /** |
| * Verify parentOf() |
| */ |
| public void testParentOf() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| assertTrue("should be true for the argument", tg.parentOf(tg)); |
| ThreadGroup tg1 = new ThreadGroup(tg, "tg1"); |
| assertTrue("tg should be parent of tg1", tg.parentOf(tg1)); |
| ThreadGroup tg2 = new ThreadGroup(tg1, "tg2"); |
| assertTrue("tg1 should be parent of tg2", tg1.parentOf(tg2)); |
| assertTrue("tg should be parent of tg2", tg.parentOf(tg2)); |
| } |
| |
| /** |
| * Verify that maxPriority is inherited by a created subgroup |
| */ |
| public void testSetMaxPriority_CreateSubgroup() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| int pri = Thread.MAX_PRIORITY - 1; |
| tg.setMaxPriority(pri); |
| ThreadGroup tg1 = new ThreadGroup(tg, "tg1"); |
| assertEquals("incorrect priority for the created subgroup", |
| pri, tg1.getMaxPriority()); |
| } |
| |
| /** |
| * Decrease group's maxPriority. |
| * Verify that threads in the thread group that already have a higher |
| * priority are not affected. |
| */ |
| public void testSetMaxPriority_Decrease() { |
| ThreadGroup group = new ThreadGroup("new"); |
| Thread t1 = new Thread(); |
| int threadPri = t1.getPriority(); |
| int newGroupMaxPri = threadPri - 1; |
| group.setMaxPriority(newGroupMaxPri); |
| assertEquals("incorrect group's priority", |
| newGroupMaxPri, group.getMaxPriority()); |
| assertEquals("thread's priority should not be affected", |
| threadPri, t1.getPriority()); |
| } |
| |
| /** |
| * Verify that lower maxPriority is set recursively to all subgroups |
| */ |
| public void testSetMaxPriority_DecreaseRecursively() { |
| String gName = "tg"; |
| int i; |
| ThreadGroup tg = new ThreadGroup(gName); |
| int pri = Thread.MAX_PRIORITY - 1; |
| tg.setMaxPriority(pri); |
| for (i = 0; i < 3; i++) { |
| new ThreadGroup(tg, gName + i); |
| } |
| ThreadGroup tg11 = new ThreadGroup(tg, gName + "11"); |
| for (i = 0; i < 3; i++) { |
| new ThreadGroup(tg11, gName + i); |
| } |
| ThreadGroup tg22 = new ThreadGroup(tg11, gName + "22"); |
| for (i = 0; i < 3; i++) { |
| new ThreadGroup(tg22, gName + i); |
| } |
| pri--; |
| tg.setMaxPriority(pri); |
| ThreadGroup list[] = new ThreadGroup[11]; |
| tg.enumerate(list); |
| for (i = 0; i < 11; i++) { |
| assertEquals("incorrect new priority for the group " + list[i], |
| pri, list[i].getMaxPriority()); |
| } |
| } |
| |
| /** |
| * Increase group's maxPriority. |
| */ |
| public void testSetMaxPriority_Increase() { |
| ThreadGroup group = new ThreadGroup("new"); |
| group.setMaxPriority(Thread.NORM_PRIORITY); |
| int newGroupMaxPri = Thread.NORM_PRIORITY + 1; |
| group.setMaxPriority(newGroupMaxPri); |
| assertEquals("incorrect group's priority", |
| newGroupMaxPri, group.getMaxPriority()); |
| } |
| |
| /** |
| * Verify that higher maxPriority is set recursively to all subgroups |
| */ |
| public void testSetMaxPriority_IncreaseRecursively() { |
| String gName = "tg"; |
| int i; |
| ThreadGroup tg = new ThreadGroup(gName); |
| int pri = Thread.NORM_PRIORITY; |
| tg.setMaxPriority(pri); |
| for (i = 0; i < 3; i++) { |
| new ThreadGroup(tg, gName + i); |
| } |
| ThreadGroup tg11 = new ThreadGroup(tg, gName + "11"); |
| for (i = 0; i < 3; i++) { |
| new ThreadGroup(tg11, gName + i); |
| } |
| ThreadGroup tg22 = new ThreadGroup(tg11, gName + "22"); |
| for (i = 0; i < 3; i++) { |
| new ThreadGroup(tg22, gName + i); |
| } |
| pri++; |
| tg.setMaxPriority(pri); |
| ThreadGroup list[] = new ThreadGroup[11]; |
| tg.enumerate(list); |
| for (i = 0; i < 11; i++) { |
| assertEquals("incorrect new priority for the group " + list[i], |
| pri, list[i].getMaxPriority()); |
| } |
| } |
| |
| /** |
| * Try to set maxPriority which is higher than the parent's one |
| */ |
| public void testSetMaxPriority_HigherParent() { |
| ThreadGroup parent = new ThreadGroup("par"); |
| int parPriority = Thread.MAX_PRIORITY - 1; |
| parent.setMaxPriority(parPriority); |
| assertEquals("incorrect priority received", |
| parPriority, parent.getMaxPriority()); |
| ThreadGroup child = new ThreadGroup(parent, "ch"); |
| child.setMaxPriority(parPriority - 1); |
| int newChildPriority = parPriority + 1; |
| child.setMaxPriority(newChildPriority); |
| // according to spec the smaller of newChildPriority and parPriority |
| // should be set |
| assertEquals("child priority should equal to parent's one", |
| parPriority, child.getMaxPriority()); |
| } |
| |
| /** |
| * Try to set maxPriority which is out of range |
| */ |
| public void testSetMaxPriority_OutOfRange() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| int curPriority = tg.getMaxPriority(); |
| int newPriority = Thread.MAX_PRIORITY + 1; |
| tg.setMaxPriority(newPriority); |
| assertEquals("Assert1: group priority should not change", |
| curPriority, tg.getMaxPriority()); |
| newPriority = Thread.MIN_PRIORITY - 1; |
| tg.setMaxPriority(newPriority); |
| assertEquals("Assert2: group priority should be set to Thread.MIN_PRIORITY", |
| Thread.MIN_PRIORITY, tg.getMaxPriority()); |
| } |
| |
| /** |
| * Verify setMaxPriority() of a system group |
| */ |
| public void testSetMaxPriority_TopLevelGroup() { |
| ThreadGroup system = Thread.currentThread().getThreadGroup(); |
| ThreadGroup parent = system.getParent(); |
| int groupCount = 1000; |
| while (parent != null && --groupCount >= 0) { |
| system = parent; |
| parent = system.getParent(); |
| } |
| int newSystemPriority = system.getMaxPriority() - 1; |
| try { |
| system.setMaxPriority(newSystemPriority); |
| assertEquals("priority has not changed", |
| newSystemPriority, system.getMaxPriority()); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Verify set/isDaemon() |
| */ |
| public void testSetDaemon() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| assertFalse("a new group should not be daemon", tg.isDaemon()); |
| tg.setDaemon(true); |
| assertTrue("daemon status has not been set", tg.isDaemon()); |
| ThreadGroup child = new ThreadGroup(tg, "child"); |
| assertTrue("a child of a daemon group should be daemon", |
| child.isDaemon()); |
| tg.setDaemon(false); |
| assertFalse("daemon status has not been removed", tg.isDaemon()); |
| } |
| |
| /** |
| * Verifies the suspend/resume() method |
| */ |
| public void testSuspend() { |
| ThreadGroup group = new ThreadGroup("Custom group"); |
| TestThread thread = new TestThread(group, "Custom thread"); |
| thread.start(); |
| group.suspend(); |
| assertFalse("the suspended thread should not finish", thread.finished); |
| thread.enough = true; |
| group.resume(); |
| try { |
| thread.join(1000); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| assertTrue("thread has not finished", thread.finished); |
| } |
| |
| /** |
| * Verify toString() output |
| */ |
| public void testToString() { |
| ThreadGroup tg = new ThreadGroup("tg"); |
| String toString = "java.lang.ThreadGroup[name=tg,maxpri="; |
| assertEquals("incorrect representation", |
| 0, tg.toString().indexOf(toString)); |
| } |
| |
| public void testUncaughtExceptionHandlers() { |
| ExceptionHandler defaultHandler = new ExceptionHandler(); |
| Thread.setDefaultUncaughtExceptionHandler(defaultHandler); |
| Thread t = new Thread("test thread"); |
| Thread.UncaughtExceptionHandler handler = t.getUncaughtExceptionHandler(); |
| assertNotNull("handler should not be null", handler); |
| assertSame("thread's thread group expected to be a handler", |
| t.getThreadGroup(), handler); |
| handler.uncaughtException(t, new RuntimeException()); |
| assertTrue("Default exception handler was not called", |
| defaultHandler.wasCalled); |
| } |
| |
| /** |
| * Verify that thread's explicit exception handler is used |
| */ |
| public void testUncaughtExceptionHandler_Explicit(){ |
| ExceptionHandler handler = new ExceptionHandler(); |
| Thread testThread = new Thread("test thread") { |
| public void run() { |
| throw new RuntimeException(); |
| } |
| }; |
| testThread.setUncaughtExceptionHandler(handler); |
| testThread.start(); |
| for(int i=0; i<10 && testThread.isAlive(); i++){ |
| try{ |
| Thread.sleep(50); |
| }catch(InterruptedException e){} |
| } |
| assertTrue("Thread's uncaught exception handler wasn't called", |
| handler.wasCalled); |
| } |
| |
| /** |
| * Verify that thread's explicit exception handler is used first |
| * even if a default UncaughtExceptionHandler is set |
| */ |
| public void testUncaughtException_ExplicitDefault() { |
| ExceptionHandler deh = new ExceptionHandler(); |
| Thread.setDefaultUncaughtExceptionHandler(deh); |
| Thread t = new Thread("test thread") { |
| public void run() { |
| throw new RuntimeException(); |
| } |
| }; |
| ExceptionHandler eh = new ExceptionHandler(); |
| t.setUncaughtExceptionHandler(eh); |
| t.start(); |
| waitTime = waitDuration; |
| while (!eh.wasCalled && !(expired = doSleep(10))) { |
| } |
| assertFalse("thread's default exception handler should not been called", |
| deh.wasCalled); |
| if (expired) { |
| fail("thread's exception handler has not been called"); |
| } |
| } |
| |
| /** |
| * Verify that uncaughtException() method of thread's parent ThreadGroup |
| * is called even if a default UncaughtExceptionHandler is set |
| */ |
| public void testUncaughtException_ThreadGroupDefault() { |
| ExceptionHandler deh = new ExceptionHandler(); |
| Thread.setDefaultUncaughtExceptionHandler(deh); |
| ThreadGroup grandPa = new ThreadGroup("grandPa"); |
| ThreadGroupHandler parent = new ThreadGroupHandler(grandPa, "parent"); |
| ThreadGroup child = new ThreadGroup(parent, "tg"); |
| String tName = "testHandler"; |
| Thread t = new Thread(child, tName) { |
| public void run() { |
| throw new RuntimeException(); |
| } |
| }; |
| t.start(); |
| waitTime = waitDuration; |
| while (!parent.handlerWasCalled && !(expired = doSleep(10))) { |
| } |
| assertFalse("thread's default exception handler should not been called", |
| deh.wasCalled); |
| if (expired) { |
| fail("threadGroup's uncaughtException() has not been called"); |
| } |
| } |
| |
| /** |
| * Verify that uncaughtException(Thread, Throwable) method |
| * where Throwable is ThreadDeath does nothing |
| */ |
| public void testUncaughtException_ThreadDeath() { |
| Thread.setDefaultUncaughtExceptionHandler(null); |
| File file = null; |
| PrintStream newErr = null; |
| try { |
| file = File.createTempFile("JUnit_ThreadUETest1", ".tmp"); |
| newErr = new PrintStream(new FileOutputStream(file)); |
| } catch (java.io.IOException e) { |
| fail("unexpected IOException 1: " + e); |
| } |
| try { |
| System.setErr(newErr); |
| } catch (SecurityException e) { |
| return; |
| } |
| Thread t = new Thread("testThreadDeath") { |
| public void run() { |
| throw new ThreadDeath(); |
| } |
| }; |
| t.start(); |
| try { |
| t.join(); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| newErr.close(); |
| System.setErr(systemErr); |
| byte buf[] = new byte[2]; |
| try { |
| FileInputStream inp = new FileInputStream(file); |
| inp.read(buf); |
| inp.close(); |
| } catch (java.io.IOException e) { |
| fail("unexpected IOException 2: " + e); |
| } |
| file.delete(); |
| assertTrue("Uncaught Exception message has not been printed", |
| buf[0] == 0); |
| } |
| |
| /** |
| * Verify that uncaughtException(Thread, Throwable) method |
| * prints a proper message |
| */ |
| public void testUncaughtException_NullPointerException() { |
| Thread.setDefaultUncaughtExceptionHandler(null); |
| File file = null; |
| PrintStream newErr = null; |
| try { |
| file = File.createTempFile("JUnit_ThreadUETest2", ".tmp"); |
| newErr = new PrintStream(new FileOutputStream(file)); |
| } catch (java.io.IOException e) { |
| fail("unexpected IOException 1: " + e); |
| } |
| try { |
| System.setErr(newErr); |
| } catch (SecurityException e) { |
| return; |
| } |
| Thread t = new Thread("testNullPointerException") { |
| public void run() { |
| throw new NullPointerException(); |
| } |
| }; |
| t.start(); |
| try { |
| t.join(); |
| } catch (InterruptedException e) { |
| fail(INTERRUPTED_MESSAGE); |
| } |
| newErr.close(); |
| System.setErr(systemErr); |
| byte buf[] = new byte[100]; |
| try { |
| FileInputStream inp = new FileInputStream(file); |
| inp.read(buf); |
| inp.close(); |
| } catch (java.io.IOException e) { |
| fail("unexpected IOException 2: " + e); |
| } |
| file.delete(); |
| assertTrue("Uncaught Exception message has not been printed", |
| new String(buf).indexOf("NullPointerException") > 0); |
| } |
| } |