Package java.lang

Source Code of java.lang.ThreadGroupTest

/*
*  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
* @version $Revision$
*/

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);
    }
}
TOP

Related Classes of java.lang.ThreadGroupTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.