ThreadGroupTest.java revision a99b695964e28a5906003d40db48cbd550fbcdf4
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.luni.tests.java.lang;
19
20import dalvik.annotation.BrokenTest;
21import dalvik.annotation.TestLevel;
22import dalvik.annotation.TestTargetNew;
23import dalvik.annotation.TestTargetClass;
24
25import java.security.Permission;
26import java.util.Vector;
27
28@TestTargetClass(ThreadGroup.class)
29public class ThreadGroupTest extends junit.framework.TestCase implements Thread.UncaughtExceptionHandler {
30
31    class MyThread extends Thread {
32        public volatile int heartBeat = 0;
33
34        public MyThread(ThreadGroup group, String name)
35                throws SecurityException, IllegalThreadStateException {
36            super(group, name);
37        }
38
39        @Override
40        public void run() {
41            while (true) {
42                heartBeat++;
43                try {
44                    Thread.sleep(50);
45                } catch (InterruptedException e) {
46                    break;
47                }
48            }
49        }
50
51        public boolean isActivelyRunning() {
52            long MAX_WAIT = 100;
53            return isActivelyRunning(MAX_WAIT);
54        }
55
56        public boolean isActivelyRunning(long maxWait) {
57            int beat = heartBeat;
58            long start = System.currentTimeMillis();
59            do {
60                Thread.yield();
61                int beat2 = heartBeat;
62                if (beat != beat2) {
63                    return true;
64                }
65            } while (System.currentTimeMillis() - start < maxWait);
66            return false;
67        }
68
69    }
70
71    private ThreadGroup rootThreadGroup = null;
72
73    private ThreadGroup initialThreadGroup = null;
74
75    /**
76     * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.String)
77     */
78    @TestTargetNew(
79        level = TestLevel.COMPLETE,
80        notes = "",
81        method = "ThreadGroup",
82        args = {java.lang.String.class}
83    )
84    public void test_ConstructorLjava_lang_String() {
85        // Test for method java.lang.ThreadGroup(java.lang.String)
86
87        // Unfortunately we have to use other APIs as well as we test the
88        // constructor
89
90        ThreadGroup newGroup = null;
91        ThreadGroup initial = getInitialThreadGroup();
92        final String name = "Test name";
93        newGroup = new ThreadGroup(name);
94        assertTrue(
95                "Has to be possible to create a subgroup of current group using simple constructor",
96                newGroup.getParent() == initial);
97        assertTrue("Name has to be correct", newGroup.getName().equals(name));
98
99        // cleanup
100        newGroup.destroy();
101
102        newGroup = new ThreadGroup("");
103        assertEquals("", newGroup.getName());
104
105        newGroup = new ThreadGroup(null);
106        assertNull(newGroup.getName());
107
108        SecurityManager oldSm = System.getSecurityManager();
109        System.setSecurityManager(sm);
110        try {
111            new ThreadGroup(name);
112            fail("Should throw SecurityException");
113        } catch (SecurityException e) {
114            // expected
115        } finally {
116           System.setSecurityManager(oldSm);
117        }
118    }
119
120    /**
121     * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.ThreadGroup,
122     *        java.lang.String)
123     */
124    @TestTargetNew(
125        level = TestLevel.COMPLETE,
126        notes = "",
127        method = "ThreadGroup",
128        args = {java.lang.ThreadGroup.class, java.lang.String.class}
129    )
130    public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_String() {
131        // Test for method java.lang.ThreadGroup(java.lang.ThreadGroup,
132        // java.lang.String)
133
134        // Unfortunately we have to use other APIs as well as we test the
135        // constructor
136
137        ThreadGroup newGroup = null;
138
139        try {
140            newGroup = new ThreadGroup(null, null);
141        } catch (NullPointerException e) {
142        }
143        assertNull("Can't create a ThreadGroup with a null parent",
144                newGroup);
145
146        newGroup = new ThreadGroup(getInitialThreadGroup(), null);
147        assertTrue("Has to be possible to create a subgroup of current group",
148                newGroup.getParent() == Thread.currentThread().getThreadGroup());
149
150        // Lets start all over
151        newGroup.destroy();
152
153        newGroup = new ThreadGroup(getRootThreadGroup(), "a name here");
154        assertTrue("Has to be possible to create a subgroup of root group",
155                newGroup.getParent() == getRootThreadGroup());
156
157        // Lets start all over
158        newGroup.destroy();
159
160        try {
161            newGroup = new ThreadGroup(newGroup, "a name here");
162        } catch (IllegalThreadStateException e) {
163            newGroup = null;
164        }
165
166        assertNull("Can't create a subgroup of a destroyed group",
167                newGroup);
168
169        try {
170            new ThreadGroup(null, "name");
171            fail("NullPointerException is not thrown.");
172        } catch(NullPointerException npe) {
173            //expected
174        }
175
176        try {
177            new ThreadGroup(newGroup, null);
178            fail("NullPointerException is not thrown.");
179        } catch(NullPointerException npe) {
180            //expected
181        }
182
183        SecurityManager oldSm = System.getSecurityManager();
184        System.setSecurityManager(sm);
185        try {
186            new ThreadGroup(getRootThreadGroup(), "a name here");
187            fail("SecurityException was not thrown.");
188        } catch (SecurityException e) {
189            // expected
190        } finally {
191           System.setSecurityManager(oldSm);
192        }
193    }
194
195    /**
196     * @tests java.lang.ThreadGroup#activeCount()
197     */
198    @TestTargetNew(
199        level = TestLevel.COMPLETE,
200        notes = "",
201        method = "activeCount",
202        args = {}
203    )
204    public void test_activeCount() {
205        // Test for method int java.lang.ThreadGroup.activeCount()
206        ThreadGroup tg = new ThreadGroup("activeCount");
207        Thread t1 = new Thread(tg, new Runnable() {
208            public void run() {
209                try {
210                    Thread.sleep(5000);
211                } catch (InterruptedException e) {
212                }
213            }
214        });
215        int beforeCount = tg.activeCount();
216        t1.start();
217        int afterCount = tg.activeCount();
218        assertTrue("count of active threads should be increased",
219                (afterCount - beforeCount) == 1);
220        t1.interrupt();
221        try {
222            t1.join();
223        } catch (InterruptedException e) {
224        }
225        // cleanup
226        tg.destroy();
227    }
228
229    /**
230     * @tests java.lang.ThreadGroup#activeGroupCount()
231     */
232    @TestTargetNew(
233        level = TestLevel.COMPLETE,
234        notes = "",
235        method = "activeGroupCount",
236        args = {}
237    )
238    public void test_activeGroupCount() {
239
240        ThreadGroup tg = new ThreadGroup("group count");
241        assertEquals("Incorrect number of groups",
242                0, tg.activeGroupCount());
243        Thread t1 = new Thread(tg, new Runnable() {
244            public void run() {
245
246            }
247        });
248        assertEquals("Incorrect number of groups",
249                0, tg.activeGroupCount());
250        t1.start();
251        assertEquals("Incorrect number of groups",
252                0, tg.activeGroupCount());
253        new ThreadGroup(tg, "test group 1");
254        assertEquals("Incorrect number of groups",
255                1, tg.activeGroupCount());
256        new ThreadGroup(tg, "test group 2");
257        assertEquals("Incorrect number of groups",
258                2, tg.activeGroupCount());
259    }
260
261    /**
262     * @tests java.lang.ThreadGroup#allowThreadSuspension(boolean)
263     */
264    @TestTargetNew(
265        level = TestLevel.COMPLETE,
266        notes = "",
267        method = "allowThreadSuspension",
268        args = {boolean.class}
269    )
270    @SuppressWarnings("deprecation")
271    public void test_allowThreadSuspensionZ() {
272        ThreadGroup tg = new ThreadGroup("thread suspension");
273        assertTrue("Thread suspention can not be changed",
274                tg.allowThreadSuspension(false));
275        assertTrue("Thread suspention can not be changed",
276                tg.allowThreadSuspension(true));
277    }
278
279    /**
280     * @tests java.lang.ThreadGroup#checkAccess()
281     */
282    @TestTargetNew(
283        level = TestLevel.COMPLETE,
284        notes = "",
285        method = "checkAccess",
286        args = {}
287    )
288    public void test_checkAccess() {
289        // Test for method void java.lang.ThreadGroup.checkAccess()
290
291        final ThreadGroup originalCurrent = getInitialThreadGroup();
292        ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
293
294        SecurityManager currentManager = System.getSecurityManager();
295        boolean passed = true;
296
297        try {
298            if (currentManager != null) {
299                testRoot.checkAccess();
300            }
301        } catch (SecurityException se) {
302            passed = false;
303        }
304
305        assertTrue("CheckAccess is no-op with no SecurityManager", passed);
306
307        testRoot.destroy();
308
309        SecurityManager oldSm = System.getSecurityManager();
310        System.setSecurityManager(sm);
311        try {
312            testRoot.checkAccess();
313            fail("Should throw SecurityException");
314        } catch (SecurityException e) {
315            // expected
316        } finally {
317           System.setSecurityManager(oldSm);
318        }
319    }
320
321    @TestTargetNew(
322        level = TestLevel.COMPLETE,
323        notes = "",
324        method = "enumerate",
325        args = {java.lang.Thread[].class}
326    )
327    public void test_enumerateLThreadArray() {
328        int numThreads = initialThreadGroup.activeCount();
329        Thread[] listOfThreads = new Thread[numThreads];
330
331        int countThread = initialThreadGroup.enumerate(listOfThreads);
332        assertEquals(numThreads, countThread);
333        assertEquals(Thread.currentThread(), listOfThreads[0]);
334
335        SecurityManager oldSm = System.getSecurityManager();
336        System.setSecurityManager(sm);
337        try {
338            initialThreadGroup.enumerate(listOfThreads);
339            fail("Should throw SecurityException");
340        } catch (SecurityException e) {
341            // expected
342        } finally {
343           System.setSecurityManager(oldSm);
344        }
345    }
346
347    @TestTargetNew(
348        level = TestLevel.COMPLETE,
349        notes = "",
350        method = "enumerate",
351        args = {java.lang.Thread[].class, boolean.class}
352    )
353    public void test_enumerateLThreadArrayLZ() {
354        int numThreads = initialThreadGroup.activeCount();
355        Thread[] listOfThreads = new Thread[numThreads];
356
357        int countThread = initialThreadGroup.enumerate(listOfThreads, false);
358        assertEquals(numThreads, countThread);
359        assertEquals(Thread.currentThread(), listOfThreads[0]);
360
361        countThread = initialThreadGroup.enumerate(listOfThreads, true);
362        assertEquals(numThreads, countThread);
363        assertEquals(Thread.currentThread(), listOfThreads[0]);
364
365        ThreadGroup subGroup = new ThreadGroup(initialThreadGroup, "Test Group 1");
366        int subThreadsCount = 3;
367        Vector<MyThread> subThreads = populateGroupsWithThreads(subGroup,
368                subThreadsCount);
369
370        countThread = initialThreadGroup.enumerate(listOfThreads, true);
371        assertEquals(numThreads, countThread);
372        assertEquals(Thread.currentThread(), listOfThreads[0]);
373
374        for(MyThread thr:subThreads) {
375            thr.start();
376        }
377        // lets give them some time to start
378        try {
379            Thread.sleep(500);
380        } catch (InterruptedException ie) {
381            fail("Should not be interrupted");
382        }
383
384        int numThreads2 = initialThreadGroup.activeCount();
385        listOfThreads = new Thread[numThreads2];
386
387        assertEquals(numThreads + subThreadsCount, numThreads2);
388
389        countThread = initialThreadGroup.enumerate(listOfThreads, true);
390        assertEquals(numThreads2, countThread);
391        assertEquals(Thread.currentThread(), listOfThreads[0]);
392
393        for(MyThread thr:subThreads) {
394            thr.interrupt();
395        }
396        // lets give them some time to die
397        try {
398            Thread.sleep(500);
399        } catch (InterruptedException ie) {
400            fail("Should not be interrupted");
401        }
402
403        int numThreads3 = initialThreadGroup.activeCount();
404        listOfThreads = new Thread[numThreads3];
405
406        assertEquals(numThreads, numThreads3);
407
408        countThread = initialThreadGroup.enumerate(listOfThreads, false);
409        assertEquals(numThreads3, countThread);
410        assertEquals(Thread.currentThread(), listOfThreads[0]);
411
412        SecurityManager oldSm = System.getSecurityManager();
413        System.setSecurityManager(sm);
414        try {
415            initialThreadGroup.enumerate(listOfThreads, true);
416            fail("Should throw SecurityException");
417        } catch (SecurityException e) {
418            // expected
419        } finally {
420           System.setSecurityManager(oldSm);
421        }
422    }
423
424    @TestTargetNew(
425        level = TestLevel.COMPLETE,
426        notes = "",
427        method = "enumerate",
428        args = {java.lang.ThreadGroup[].class}
429    )
430    public void test_enumerateLThreadGroupArray() {
431        int numGroupThreads = initialThreadGroup.activeGroupCount();
432        ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads];
433
434        int countGroupThread = initialThreadGroup.enumerate(listOfGroups);
435        assertEquals(numGroupThreads, countGroupThread);
436
437        ThreadGroup[] listOfGroups1 = new ThreadGroup[numGroupThreads + 1];
438        countGroupThread = initialThreadGroup.enumerate(listOfGroups1);
439        assertEquals(numGroupThreads, countGroupThread);
440        assertNull(listOfGroups1[listOfGroups1.length - 1]);
441
442        ThreadGroup[] listOfGroups2 = new ThreadGroup[numGroupThreads - 1];
443        countGroupThread = initialThreadGroup.enumerate(listOfGroups2);
444        assertEquals(numGroupThreads - 1, countGroupThread);
445
446        ThreadGroup thrGroup1 = new ThreadGroup("Test Group 1");
447        countGroupThread = thrGroup1.enumerate(listOfGroups);
448        assertEquals(0, countGroupThread);
449
450        SecurityManager oldSm = System.getSecurityManager();
451        System.setSecurityManager(sm);
452        try {
453            initialThreadGroup.enumerate(listOfGroups);
454            fail("Should throw SecurityException");
455        } catch (SecurityException e) {
456            // expected
457        } finally {
458           System.setSecurityManager(oldSm);
459        }
460     }
461
462    @TestTargetNew(
463        level = TestLevel.COMPLETE,
464        notes = "",
465        method = "enumerate",
466        args = {java.lang.ThreadGroup[].class, boolean.class}
467    )
468    public void test_enumerateLThreadGroupArrayLZ() {
469        ThreadGroup thrGroup = new ThreadGroup("Test Group 1");
470        Vector<MyThread> subThreads = populateGroupsWithThreads(thrGroup, 3);
471        int numGroupThreads = thrGroup.activeGroupCount();
472        ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads];
473
474        assertEquals(0, thrGroup.enumerate(listOfGroups, true));
475        assertEquals(0, thrGroup.enumerate(listOfGroups, false));
476
477        for(MyThread thr:subThreads) {
478            thr.start();
479        }
480
481        numGroupThreads = thrGroup.activeGroupCount();
482        listOfGroups = new ThreadGroup[numGroupThreads];
483
484        assertEquals(0, thrGroup.enumerate(listOfGroups, true));
485        assertEquals(0, thrGroup.enumerate(listOfGroups, false));
486
487        ThreadGroup subGroup1 = new ThreadGroup(thrGroup, "Test Group 2");
488        Vector<MyThread> subThreads1 = populateGroupsWithThreads(subGroup1, 3);
489        numGroupThreads = thrGroup.activeGroupCount();
490        listOfGroups = new ThreadGroup[numGroupThreads];
491
492        assertEquals(1, thrGroup.enumerate(listOfGroups, true));
493        assertEquals(1, thrGroup.enumerate(listOfGroups, false));
494
495        for(MyThread thr:subThreads1) {
496            thr.start();
497        }
498        numGroupThreads = thrGroup.activeGroupCount();
499        listOfGroups = new ThreadGroup[numGroupThreads];
500
501        assertEquals(1, thrGroup.enumerate(listOfGroups, true));
502        assertEquals(1, thrGroup.enumerate(listOfGroups, false));
503
504        for(MyThread thr:subThreads) {
505            thr.interrupt();
506         }
507
508        ThreadGroup subGroup2 = new ThreadGroup(subGroup1, "Test Group 3");
509        Vector<MyThread> subThreads2 = populateGroupsWithThreads(subGroup2, 3);
510        numGroupThreads = thrGroup.activeGroupCount();
511        listOfGroups = new ThreadGroup[numGroupThreads];
512
513        assertEquals(2, thrGroup.enumerate(listOfGroups, true));
514        assertEquals(1, thrGroup.enumerate(listOfGroups, false));
515
516        SecurityManager oldSm = System.getSecurityManager();
517        System.setSecurityManager(sm);
518        try {
519            thrGroup.enumerate(listOfGroups, true);
520            fail("Should throw SecurityException");
521        } catch (SecurityException e) {
522            // expected
523        } finally {
524           System.setSecurityManager(oldSm);
525        }
526    }
527
528    /**
529     * @tests java.lang.ThreadGroup#destroy()
530     */
531    @TestTargetNew(
532        level = TestLevel.COMPLETE,
533        notes = "",
534        method = "destroy",
535        args = {}
536    )
537    public void test_destroy() {
538        // Test for method void java.lang.ThreadGroup.destroy()
539
540        final ThreadGroup originalCurrent = getInitialThreadGroup();
541        ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
542        final int DEPTH = 4;
543        final Vector<ThreadGroup> subgroups = buildRandomTreeUnder(testRoot, DEPTH);
544
545        // destroy them all
546        testRoot.destroy();
547
548        for (int i = 0; i < subgroups.size(); i++) {
549            ThreadGroup child = subgroups.elementAt(i);
550            assertEquals("Destroyed child can't have children", 0, child
551                    .activeCount());
552            boolean passed = false;
553            try {
554                child.destroy();
555            } catch (IllegalThreadStateException e) {
556                passed = true;
557            }
558
559            assertTrue("Destroyed child can't be destroyed again", passed);
560        }
561
562        testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)");
563        testRoot.setDaemon(true);
564
565        ThreadGroup child = new ThreadGroup(testRoot, "daemon child");
566
567        // If we destroy the last daemon's child, the daemon should get destroyed
568        // as well
569        child.destroy();
570
571        boolean passed = false;
572        try {
573            child.destroy();
574        } catch (IllegalThreadStateException e) {
575            passed = true;
576        }
577
578        assertTrue("Daemon should have been destroyed already", passed);
579
580        passed = false;
581        try {
582            testRoot.destroy();
583        } catch (IllegalThreadStateException e) {
584            passed = true;
585        }
586
587        assertTrue("Daemon parent should have been destroyed automatically",
588                passed);
589
590        assertTrue(
591                "Destroyed daemon's child should not be in daemon's list anymore",
592                !arrayIncludes(groups(testRoot), child));
593        assertTrue("Destroyed daemon should not be in parent's list anymore",
594                !arrayIncludes(groups(originalCurrent), testRoot));
595
596        testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)");
597        testRoot.setDaemon(true);
598        Thread noOp = new Thread(testRoot, null, "no-op thread") {
599            @Override
600            public void run() {
601            }
602        };
603        noOp.start();
604
605        // Wait for the no-op thread to run inside daemon ThreadGroup
606        try {
607            noOp.join();
608        } catch (InterruptedException ie) {
609            fail("Should not be interrupted");
610        }
611
612
613        passed = false;
614        try {
615            child.destroy();
616        } catch (IllegalThreadStateException e) {
617            passed = true;
618        }
619
620        assertTrue(
621                "Daemon group should have been destroyed already when last thread died",
622                passed);
623
624        testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)");
625        noOp = new Thread(testRoot, null, "no-op thread") {
626            @Override
627            public void run() {
628                try {
629                    Thread.sleep(500);
630                } catch (InterruptedException ie) {
631                    fail("Should not be interrupted");
632                }
633            }
634        };
635
636        // Has to execute the next lines in an interval < the sleep interval of
637        // the no-op thread
638        noOp.start();
639        passed = false;
640        try {
641            testRoot.destroy();
642        } catch (IllegalThreadStateException its) {
643            passed = true;
644        }
645        assertTrue("Can't destroy a ThreadGroup that has threads", passed);
646
647        // But after the thread dies, we have to be able to destroy the thread
648        // group
649        try {
650            noOp.join();
651        } catch (InterruptedException ie) {
652            fail("Should not be interrupted");
653        }
654
655        passed = true;
656        try {
657            testRoot.destroy();
658        } catch (IllegalThreadStateException its) {
659            passed = false;
660        }
661        assertTrue(
662                "Should be able to destroy a ThreadGroup that has no threads",
663                passed);
664
665        ThreadGroup tg = new ThreadGroup("ThreadGroup");
666        SecurityManager oldSm = System.getSecurityManager();
667        System.setSecurityManager(sm);
668        try {
669            originalCurrent.destroy();
670            fail("Should throw SecurityException");
671        } catch (SecurityException e) {
672            // expected
673        } finally {
674           System.setSecurityManager(oldSm);
675        }
676    }
677
678    /**
679     * @tests java.lang.ThreadGroup#destroy()
680     */
681    @TestTargetNew(
682        level = TestLevel.PARTIAL,
683        notes = "Verifies IllegalThreadStateException.",
684        method = "destroy",
685        args = {}
686    )
687    public void test_destroy_subtest0() {
688        ThreadGroup group1 = new ThreadGroup("test_destroy_subtest0");
689        group1.destroy();
690        try {
691            new Thread(group1, "test_destroy_subtest0");
692            fail("should throw IllegalThreadStateException");
693        } catch (IllegalThreadStateException e) {
694        }
695    }
696
697    /**
698     * @tests java.lang.ThreadGroup#getMaxPriority()
699     */
700    @TestTargetNew(
701        level = TestLevel.COMPLETE,
702        notes = "",
703        method = "getMaxPriority",
704        args = {}
705    )
706    public void test_getMaxPriority() {
707        // Test for method int java.lang.ThreadGroup.getMaxPriority()
708        final ThreadGroup originalCurrent = getInitialThreadGroup();
709        ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
710
711        boolean passed = true;
712        try {
713            testRoot.setMaxPriority(Thread.MIN_PRIORITY);
714        } catch (IllegalArgumentException iae) {
715            passed = false;
716        }
717        assertTrue("Should be able to set priority", passed);
718
719        assertTrue("New value should be the same as we set", testRoot
720                .getMaxPriority() == Thread.MIN_PRIORITY);
721
722        testRoot.destroy();
723
724    }
725
726    /**
727     * @tests java.lang.ThreadGroup#getName()
728     */
729    @TestTargetNew(
730        level = TestLevel.COMPLETE,
731        notes = "",
732        method = "getName",
733        args = {}
734    )
735    public void test_getName() {
736        // Test for method java.lang.String java.lang.ThreadGroup.getName()
737        final ThreadGroup originalCurrent = getInitialThreadGroup();
738        final String name = "Test group";
739        final ThreadGroup testRoot = new ThreadGroup(originalCurrent, name);
740
741        assertTrue("Setting a name&getting does not work", testRoot.getName()
742                .equals(name));
743
744        testRoot.destroy();
745
746    }
747
748    /**
749     * @tests java.lang.ThreadGroup#getParent()
750     */
751    @TestTargetNew(
752        level = TestLevel.COMPLETE,
753        notes = "",
754        method = "getParent",
755        args = {}
756    )
757    public void test_getParent() {
758        // Test for method java.lang.ThreadGroup
759        // java.lang.ThreadGroup.getParent()
760        final ThreadGroup originalCurrent = getInitialThreadGroup();
761        ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
762
763        assertTrue("Parent is wrong", testRoot.getParent() == originalCurrent);
764
765        // Create some groups, nested some levels.
766        final int TOTAL_DEPTH = 5;
767        ThreadGroup current = testRoot;
768        Vector<ThreadGroup> groups = new Vector<ThreadGroup>();
769        // To maintain the invariant that a thread in the Vector is parent
770        // of the next one in the collection (and child of the previous one)
771        groups.addElement(testRoot);
772
773        for (int i = 0; i < TOTAL_DEPTH; i++) {
774            current = new ThreadGroup(current, "level " + i);
775            groups.addElement(current);
776        }
777
778        // Now we walk the levels down, checking if parent is ok
779        for (int i = 1; i < groups.size(); i++) {
780            current = groups.elementAt(i);
781            ThreadGroup previous = groups.elementAt(i - 1);
782            assertTrue("Parent is wrong", current.getParent() == previous);
783        }
784
785        final ThreadGroup[] checkAccessGroup = new ThreadGroup[1];
786        class SecurityManagerImpl extends MutableSecurityManager {
787            @Override
788            public void checkAccess(ThreadGroup group) {
789                checkAccessGroup[0] = group;
790            }
791        }
792        SecurityManagerImpl sm = new SecurityManagerImpl();
793        //add permission to allow reset of security manager
794        sm.addPermission(MutableSecurityManager.SET_SECURITY_MANAGER);
795
796        ThreadGroup parent;
797        try {
798            // To see if it checks Thread creation with our SecurityManager
799            System.setSecurityManager(sm);
800            parent = testRoot.getParent();
801        } finally {
802            // restore original, no side-effects
803            System.setSecurityManager(null);
804        }
805        assertTrue("checkAccess with incorrect group",
806                checkAccessGroup[0] == parent);
807
808        testRoot.destroy();
809    }
810
811    /**
812     * @tests java.lang.ThreadGroup#interrupt()
813     */
814    private static boolean interrupted = false;
815    @TestTargetNew(
816        level = TestLevel.COMPLETE,
817        notes = "",
818        method = "interrupt",
819        args = {}
820    )
821    public void test_interrupt() {
822
823        Thread.setDefaultUncaughtExceptionHandler(this);
824        ThreadGroup tg = new ThreadGroup("interrupt");
825        Thread t1 = new Thread(tg, new Runnable() {
826            public void run() {
827                try {
828                    Thread.sleep(5000);
829                } catch (InterruptedException e) {
830                    fail("ok");
831                }
832            }
833        });
834        assertFalse("Incorrect state of thread", interrupted);
835        t1.start();
836        assertFalse("Incorrect state of thread", interrupted);
837        t1.interrupt();
838        try {
839            t1.join();
840        } catch (InterruptedException e) {
841        }
842        assertTrue("Incorrect state of thread", interrupted);
843        tg.destroy();
844
845        ThreadGroup threadGroup = new ThreadGroup("securityCheck");
846        SecurityManager oldSm = System.getSecurityManager();
847        System.setSecurityManager(sm);
848        try {
849            threadGroup.interrupt();
850            fail("Should throw SecurityException");
851        } catch (SecurityException e) {
852            // expected
853        } finally {
854           System.setSecurityManager(oldSm);
855        }
856    }
857
858    /**
859     * @tests java.lang.ThreadGroup#isDaemon()
860     */
861    @TestTargetNew(
862        level = TestLevel.COMPLETE,
863        notes = "",
864        method = "isDaemon",
865        args = {}
866    )
867    public void test_isDaemon() {
868        // Test for method boolean java.lang.ThreadGroup.isDaemon()
869        daemonTests();
870    }
871
872    /**
873     * @tests java.lang.ThreadGroup#isDestroyed()
874     */
875    @TestTargetNew(
876        level = TestLevel.COMPLETE,
877        notes = "",
878        method = "isDestroyed",
879        args = {}
880    )
881    public void test_isDestroyed() {
882        final ThreadGroup originalCurrent = getInitialThreadGroup();
883        final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
884                "Test group");
885        assertFalse("Test group is not destroyed yet",
886                testRoot.isDestroyed());
887        testRoot.destroy();
888        assertTrue("Test group already destroyed",
889                testRoot.isDestroyed());
890    }
891
892    /**
893     * @tests java.lang.ThreadGroup#list()
894     */
895    @TestTargetNew(
896        level = TestLevel.COMPLETE,
897        notes = "",
898        method = "list",
899        args = {}
900    )
901    public void test_list() {
902        // Test for method void java.lang.ThreadGroup.list()
903
904        final ThreadGroup originalCurrent = getInitialThreadGroup();
905        // wipeSideEffectThreads destroy all side effect of threads created in
906        // java.lang.Thread
907        boolean result = wipeSideEffectThreads(originalCurrent);
908        if (result == false) {
909            fail("wipe threads in test_list() not successful");
910        }
911        final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
912                "Test group");
913
914        // First save the original System.out
915        java.io.PrintStream originalOut = System.out;
916
917        try {
918            java.io.ByteArrayOutputStream contentsStream = new java.io.ByteArrayOutputStream(
919                    100);
920            java.io.PrintStream newOut = new java.io.PrintStream(contentsStream);
921
922            // We have to "redirect" System.out to test the method 'list'
923            System.setOut(newOut);
924
925            originalCurrent.list();
926
927            /*
928             * The output has to look like this
929             *
930             * java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main]
931             * java.lang.ThreadGroup[name=Test group,maxpri=10]
932             *
933             */
934
935            String contents = new String(contentsStream.toByteArray());
936            boolean passed = (contents.indexOf("ThreadGroup[name=main") != -1) &&
937                             (contents.indexOf("Thread[") != -1) &&
938                             (contents.indexOf("ThreadGroup[name=Test group") != -1);
939            assertTrue("'list()' does not print expected contents. "
940                    + "Result from list: "
941                    + contents, passed);
942            // Do proper cleanup
943            testRoot.destroy();
944
945        } finally {
946            // No matter what, we need to restore the original System.out
947            System.setOut(originalOut);
948        }
949
950    }
951
952    /**
953     * @tests java.lang.ThreadGroup#parentOf(java.lang.ThreadGroup)
954     */
955    @TestTargetNew(
956        level = TestLevel.COMPLETE,
957        notes = "",
958        method = "parentOf",
959        args = {java.lang.ThreadGroup.class}
960    )
961    public void test_parentOfLjava_lang_ThreadGroup() {
962        // Test for method boolean
963        // java.lang.ThreadGroup.parentOf(java.lang.ThreadGroup)
964        final ThreadGroup originalCurrent = getInitialThreadGroup();
965        final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
966                "Test group");
967        final int DEPTH = 4;
968        buildRandomTreeUnder(testRoot, DEPTH);
969
970        final ThreadGroup[] allChildren = allGroups(testRoot);
971        for (ThreadGroup element : allChildren) {
972            assertTrue("Have to be parentOf all children", testRoot
973                    .parentOf(element));
974        }
975
976        assertTrue("Have to be parentOf itself", testRoot.parentOf(testRoot));
977
978        testRoot.destroy();
979        assertTrue("Parent can't have test group as subgroup anymore",
980                !arrayIncludes(groups(testRoot.getParent()), testRoot));
981
982        try {
983            System.setSecurityManager(new MutableSecurityManager(MutableSecurityManager.SET_SECURITY_MANAGER));
984            assertTrue("Should not be parent", !testRoot
985                    .parentOf(originalCurrent));
986        } finally {
987            System.setSecurityManager(null);
988        }
989    }
990
991    /**
992     * @tests java.lang.ThreadGroup#resume()
993     */
994    @TestTargetNew(
995        level = TestLevel.COMPLETE,
996        notes = "",
997        method = "resume",
998        args = {}
999    )
1000   @SuppressWarnings("deprecation")
1001   @BrokenTest("Thread.resume is implemented on some RI")
1002    public void test_resume() throws OutOfMemoryError {
1003        // Test for method void java.lang.ThreadGroup.resume()
1004        final ThreadGroup originalCurrent = getInitialThreadGroup();
1005
1006        final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
1007                "Test group");
1008        final int DEPTH = 2;
1009        buildRandomTreeUnder(testRoot, DEPTH);
1010
1011        final int THREADS_PER_GROUP = 2;
1012        final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
1013                THREADS_PER_GROUP);
1014        try {
1015            for (int i = 0; i < threads.size(); i++) {
1016                Thread t = threads.elementAt(i);
1017                t.start();
1018            }
1019        } catch (OutOfMemoryError e) {
1020            for (int i = 0; i < threads.size(); i++) {
1021                Thread t = threads.elementAt(i);
1022                t.interrupt();
1023            }
1024            throw e;
1025        }
1026
1027        try {
1028            testRoot.resume();
1029            fail("Thread.resume() is not supported and throws an UOE on Android.");
1030        } catch (UnsupportedOperationException e) {
1031            // expected
1032        }
1033
1034
1035        for (int i = 0; i < threads.size(); i++) {
1036            MyThread t = threads.elementAt(i);
1037            t.interrupt();
1038        }
1039
1040        // Make sure we do cleanup before returning
1041        testRoot.destroy();
1042
1043        assertEquals("Method destroy must have problems",
1044                0, testRoot.activeCount());
1045
1046        SecurityManager oldSm = System.getSecurityManager();
1047        System.setSecurityManager(sm);
1048        try {
1049            originalCurrent.resume();
1050            fail("Should throw SecurityException");
1051        } catch (SecurityException e) {
1052            // expected
1053        } finally {
1054           System.setSecurityManager(oldSm);
1055        }
1056    }
1057
1058    /**
1059     * @tests java.lang.ThreadGroup#setDaemon(boolean)
1060     */
1061    @TestTargetNew(
1062        level = TestLevel.COMPLETE,
1063        notes = "",
1064        method = "setDaemon",
1065        args = {boolean.class}
1066    )
1067    public void test_setDaemonZ() {
1068        // Test for method void java.lang.ThreadGroup.setDaemon(boolean)
1069        daemonTests();
1070
1071        final ThreadGroup testRoot = new ThreadGroup("Test group");
1072
1073        testRoot.setDaemon(true);
1074
1075        SecurityManager oldSm = System.getSecurityManager();
1076        System.setSecurityManager(sm);
1077
1078        try {
1079            new ThreadGroup("");
1080            fail("Should throw SecurityException");
1081        } catch (SecurityException e) {
1082            // expected
1083        } finally {
1084           System.setSecurityManager(oldSm);
1085        }
1086    }
1087
1088    /**
1089     * @tests java.lang.ThreadGroup#setMaxPriority(int)
1090     */
1091    @TestTargetNew(
1092        level = TestLevel.COMPLETE,
1093        notes = "",
1094        method = "setMaxPriority",
1095        args = {int.class}
1096    )
1097    public void test_setMaxPriorityI() {
1098        // Test for method void java.lang.ThreadGroup.setMaxPriority(int)
1099        final ThreadGroup originalCurrent = getInitialThreadGroup();
1100        ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group");
1101
1102        boolean passed;
1103
1104        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1105
1106        int currentMax = testRoot.getMaxPriority();
1107        testRoot.setMaxPriority(Thread.MAX_PRIORITY + 1);
1108        passed = testRoot.getMaxPriority() == currentMax;
1109        assertTrue(
1110                "setMaxPriority: Any value higher than the current one is ignored. Before: "
1111                        + currentMax + " , after: " + testRoot.getMaxPriority(),
1112                passed);
1113
1114        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1115
1116        currentMax = testRoot.getMaxPriority();
1117        testRoot.setMaxPriority(Thread.MIN_PRIORITY - 1);
1118        passed = testRoot.getMaxPriority() == Thread.MIN_PRIORITY;
1119        assertTrue(
1120                "setMaxPriority: Any value smaller than MIN_PRIORITY is adjusted to MIN_PRIORITY. Before: "
1121                        + currentMax + " , after: " + testRoot.getMaxPriority(),
1122                passed);
1123
1124        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1125
1126        testRoot.destroy();
1127        testRoot = new ThreadGroup(originalCurrent, "Test group");
1128
1129        // Create some groups, nested some levels. Each level will have maxPrio
1130        // 1 unit smaller than the parent's. However, there can't be a group
1131        // with priority < Thread.MIN_PRIORITY
1132        final int TOTAL_DEPTH = testRoot.getMaxPriority() - Thread.MIN_PRIORITY
1133                - 2;
1134        ThreadGroup current = testRoot;
1135        for (int i = 0; i < TOTAL_DEPTH; i++) {
1136            current = new ThreadGroup(current, "level " + i);
1137        }
1138
1139        // Now we walk the levels down, changing the maxPrio and later verifying
1140        // that the value is indeed 1 unit smaller than the parent's maxPrio.
1141        int maxPrio, parentMaxPrio;
1142        current = testRoot;
1143
1144        // To maintain the invariant that when we are to modify a child,
1145        // its maxPriority is always 1 unit smaller than its parent's.
1146        // We have to set it for the root manually, and the loop does the rest
1147        // for all the other sub-levels
1148        current.setMaxPriority(current.getParent().getMaxPriority() - 1);
1149
1150        for (int i = 0; i < TOTAL_DEPTH; i++) {
1151            maxPrio = current.getMaxPriority();
1152            parentMaxPrio = current.getParent().getMaxPriority();
1153
1154            ThreadGroup[] children = groups(current);
1155            assertEquals("Can only have 1 subgroup", 1, children.length);
1156            current = children[0];
1157            assertTrue(
1158                    "Had to be 1 unit smaller than parent's priority in iteration="
1159                            + i + " checking->" + current,
1160                    maxPrio == parentMaxPrio - 1);
1161            current.setMaxPriority(maxPrio - 1);
1162
1163            // The next test is sort of redundant, since in next iteration it
1164            // will be the parent tGroup, so the test will be done.
1165            assertTrue("Had to be possible to change max priority", current
1166                    .getMaxPriority() == maxPrio - 1);
1167        }
1168
1169        assertTrue(
1170                "Priority of leaf child group has to be much smaller than original root group",
1171                current.getMaxPriority() == testRoot.getMaxPriority()
1172                        - TOTAL_DEPTH);
1173
1174        testRoot.destroy();
1175
1176        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1177
1178        passed = true;
1179        testRoot = new ThreadGroup(originalCurrent, "Test group");
1180        try {
1181            testRoot.setMaxPriority(Thread.MAX_PRIORITY);
1182        } catch (IllegalArgumentException iae) {
1183            passed = false;
1184        }
1185        assertTrue(
1186                "Max Priority = Thread.MAX_PRIORITY should be possible if the test is run with default system ThreadGroup as root",
1187                passed);
1188        testRoot.destroy();
1189
1190        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1191
1192        passed = true;
1193        testRoot = new ThreadGroup(originalCurrent, "Test group");
1194        System.setSecurityManager(new MutableSecurityManager(MutableSecurityManager.SET_SECURITY_MANAGER));
1195        try {
1196            try {
1197                testRoot.setMaxPriority(Thread.MIN_PRIORITY);
1198            } catch (IllegalArgumentException iae) {
1199                passed = false;
1200            }
1201        } finally {
1202            System.setSecurityManager(null);
1203        }
1204        assertTrue(
1205                "Min Priority = Thread.MIN_PRIORITY should be possible, always",
1206                passed);
1207        testRoot.destroy();
1208
1209        try {
1210            System.setSecurityManager(new MutableSecurityManager(MutableSecurityManager.SET_SECURITY_MANAGER));
1211            originalCurrent.setMaxPriority(Thread.MAX_PRIORITY);
1212        } finally {
1213            System.setSecurityManager(null);
1214        }
1215
1216        SecurityManager oldSm = System.getSecurityManager();
1217        System.setSecurityManager(sm);
1218
1219        try {
1220            testRoot.setMaxPriority(Thread.MAX_PRIORITY);
1221            fail("Should throw SecurityException");
1222        } catch (SecurityException e) {
1223            // expected
1224        } finally {
1225           System.setSecurityManager(oldSm);
1226        }
1227    }
1228
1229    /**
1230     * @tests java.lang.ThreadGroup#stop()
1231     */
1232    @TestTargetNew(
1233        level = TestLevel.COMPLETE,
1234        notes = "",
1235        method = "stop",
1236        args = {}
1237    )
1238    @BrokenTest("stop() method not implemented.")
1239    @SuppressWarnings("deprecation")
1240    public void test_stop() throws OutOfMemoryError {
1241        // Test for method void java.lang.ThreadGroup.stop()
1242        final ThreadGroup originalCurrent = getInitialThreadGroup();
1243
1244        final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
1245                "Test group");
1246        final int DEPTH = 2;
1247        buildRandomTreeUnder(testRoot, DEPTH);
1248
1249        final int THREADS_PER_GROUP = 2;
1250        final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
1251                THREADS_PER_GROUP);
1252
1253        try {
1254            for (int i = 0; i < threads.size(); i++) {
1255                Thread t = threads.elementAt(i);
1256                t.start();
1257            }
1258        } catch (OutOfMemoryError e) {
1259            for (int i = 0; i < threads.size(); i++) {
1260                Thread t = threads.elementAt(i);
1261                t.interrupt();
1262            }
1263            throw e;
1264        }
1265
1266        // Now that they are all running, let's stop the ThreadGroup
1267        try {
1268            testRoot.stop();
1269            fail("Thread.stop() is not supported and throws an UOE on Android.");
1270        } catch (UnsupportedOperationException e) {
1271            // expected
1272        }
1273
1274        for (int i = 0; i < threads.size(); i++) {
1275            Thread t = threads.elementAt(i);
1276            t.interrupt();
1277        }
1278
1279        // To make sure that even if we fail, we exit in a clean state
1280        testRoot.destroy();
1281
1282        assertEquals("Method destroy (or wipeAllThreads) must have problems",
1283                0, testRoot.activeCount());
1284
1285        SecurityManager oldSm = System.getSecurityManager();
1286        System.setSecurityManager(sm);
1287
1288        try {
1289            originalCurrent.stop();
1290            fail("Should throw SecurityException");
1291        } catch (SecurityException e) {
1292            // expected
1293        } finally {
1294           System.setSecurityManager(oldSm);
1295        }
1296    }
1297
1298    /**
1299     * @tests java.lang.ThreadGroup#suspend()
1300     */
1301    @TestTargetNew(
1302        level = TestLevel.COMPLETE,
1303        notes = "",
1304        method = "suspend",
1305        args = {}
1306    )
1307    @BrokenTest("suspend() method not implemented.")
1308    @SuppressWarnings("deprecation")
1309    public void test_suspend() throws OutOfMemoryError {
1310        // Test for method void java.lang.ThreadGroup.suspend()
1311        final ThreadGroup originalCurrent = getInitialThreadGroup();
1312
1313        final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
1314                "Test group");
1315        final int DEPTH = 2;
1316        buildRandomTreeUnder(testRoot, DEPTH);
1317
1318        final int THREADS_PER_GROUP = 2;
1319        final Vector<MyThread> threads = populateGroupsWithThreads(testRoot,
1320                THREADS_PER_GROUP);
1321
1322        try {
1323            for (int i = 0; i < threads.size(); i++) {
1324                Thread t = threads.elementAt(i);
1325                t.start();
1326            }
1327        } catch (OutOfMemoryError e) {
1328            for (int i = 0; i < threads.size(); i++) {
1329                Thread t = threads.elementAt(i);
1330                t.interrupt();
1331            }
1332            throw e;
1333        }
1334
1335        try {
1336            testRoot.suspend();
1337            fail("Thread.suspend() is not supported and throws an UOE on Android.");
1338        } catch (UnsupportedOperationException e) {
1339            // expected
1340        }
1341
1342        for (int i = 0; i < threads.size(); i++) {
1343            Thread t = threads.elementAt(i);
1344            t.interrupt();
1345         }
1346        // Make sure we cleanup before returning from the method
1347        testRoot.destroy();
1348
1349        assertEquals("Method destroy (or wipeAllThreads) must have problems",
1350                0, testRoot.activeCount());
1351
1352        SecurityManager oldSm = System.getSecurityManager();
1353        System.setSecurityManager(sm);
1354        try {
1355            originalCurrent.suspend();
1356            fail("Should throw SecurityException");
1357        } catch (SecurityException e) {
1358            // expected
1359        } finally {
1360           System.setSecurityManager(oldSm);
1361        }
1362    }
1363
1364    /**
1365     * @tests java.lang.ThreadGroup#toString()
1366     */
1367    @TestTargetNew(
1368        level = TestLevel.COMPLETE,
1369        notes = "",
1370        method = "toString",
1371        args = {}
1372    )
1373    public void test_toString() {
1374        // Test for method java.lang.String java.lang.ThreadGroup.toString()
1375        final ThreadGroup originalCurrent = getInitialThreadGroup();
1376        final String tGroupName = "Test group";
1377
1378        // Our own subclass
1379        class MyThreadGroup extends ThreadGroup {
1380            // Have to define a constructor since there's no default one
1381            public MyThreadGroup(ThreadGroup parent, String name) {
1382                super(parent, name);
1383            }
1384        }
1385        ;
1386
1387        ThreadGroup testRoot = new MyThreadGroup(originalCurrent, tGroupName);
1388        final String toString = testRoot.toString();
1389
1390        StringBuffer expectedResult = new StringBuffer();
1391        expectedResult.append(testRoot.getClass().getName());
1392        expectedResult.append("[name=");
1393        expectedResult.append(tGroupName);
1394        expectedResult.append(",maxpri=");
1395        expectedResult.append(testRoot.getMaxPriority());
1396        expectedResult.append("]");
1397
1398        String expectedValue = expectedResult.toString();
1399
1400        assertTrue("toString does not follow the Java language spec.", toString
1401                .equals(expectedValue));
1402
1403        testRoot.destroy();
1404    }
1405
1406    /**
1407     * @tests java.lang.ThreadGroup#uncaughtException(java.lang.Thread,
1408     *        java.lang.Throwable)
1409     */
1410    @TestTargetNew(
1411        level = TestLevel.COMPLETE,
1412        notes = "",
1413        method = "uncaughtException",
1414        args = {java.lang.Thread.class, java.lang.Throwable.class}
1415    )
1416    @SuppressWarnings("deprecation")
1417    public void test_uncaughtExceptionLjava_lang_ThreadLjava_lang_Throwable() {
1418        // Test for method void
1419        // java.lang.ThreadGroup.uncaughtException(java.lang.Thread,
1420        // java.lang.Throwable)
1421
1422        final ThreadGroup originalCurrent = getInitialThreadGroup();
1423
1424        // indices for the array defined below
1425        final int TEST_DEATH = 0;
1426        final int TEST_OTHER = 1;
1427        final int TEST_EXCEPTION_IN_UNCAUGHT = 2;
1428        final int TEST_OTHER_THEN_DEATH = 3;
1429        final int TEST_FORCING_THROW_THREAD_DEATH = 4;
1430        final int TEST_KILLING = 5;
1431        final int TEST_DEATH_AFTER_UNCAUGHT = 6;
1432
1433        final boolean[] passed = new boolean[] { false, false, false, false,
1434                false, false, false };
1435
1436        ThreadGroup testRoot;
1437        Thread thread;
1438
1439        // Our own exception class
1440        class TestException extends RuntimeException {
1441            private static final long serialVersionUID = 1L;
1442        }
1443
1444        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1445        // - - - - - - -
1446        testRoot = new ThreadGroup(originalCurrent,
1447                "Test Forcing a throw of ThreadDeath") {
1448            @Override
1449            public void uncaughtException(Thread t, Throwable e) {
1450                if (e instanceof ThreadDeath) {
1451                    passed[TEST_FORCING_THROW_THREAD_DEATH] = true;
1452                }
1453                // always forward, any exception
1454                super.uncaughtException(t, e);
1455            }
1456        };
1457
1458        // Test if a Thread tells its ThreadGroup about ThreadDeath
1459        thread = new Thread(testRoot, null, "suicidal thread") {
1460            @Override
1461            public void run() {
1462                throw new ThreadDeath();
1463            }
1464        };
1465        thread.start();
1466        try {
1467            thread.join();
1468        } catch (InterruptedException ie) {
1469            fail("Should not have been interrupted");
1470        }
1471        testRoot.destroy();
1472        assertTrue(
1473                "Any thread should notify its ThreadGroup about its own death, even if suicide:"
1474                        + testRoot, passed[TEST_FORCING_THROW_THREAD_DEATH]);
1475        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1476        // - - - - - - -
1477
1478        testRoot = new ThreadGroup(originalCurrent, "Test ThreadDeath") {
1479            @Override
1480            public void uncaughtException(Thread t, Throwable e) {
1481                passed[TEST_DEATH] = false;
1482                // always forward, any exception
1483                super.uncaughtException(t, e);
1484            }
1485        };
1486
1487        // Test if a Thread tells its ThreadGroup about ThreadDeath
1488        passed[TEST_DEATH] = true;
1489        thread = new Thread(testRoot, null, "no-op thread");
1490        thread.start();
1491        try {
1492            thread.join();
1493        } catch (InterruptedException ie) {
1494            fail("Should not have been interrupted");
1495        }
1496        testRoot.destroy();
1497        assertTrue("A thread should not call uncaughtException when it dies:"
1498                + testRoot, passed[TEST_DEATH]);
1499        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1500        // - - - - - - -
1501
1502        testRoot = new ThreadGroup(originalCurrent, "Test other Exception") {
1503            @Override
1504            public void uncaughtException(Thread t, Throwable e) {
1505                if (e instanceof TestException) {
1506                    passed[TEST_OTHER] = true;
1507                } else {
1508                    // only forward exceptions other than our test
1509                    super.uncaughtException(t, e);
1510                }
1511            }
1512        };
1513
1514        // Test if a Thread tells its ThreadGroup about an Exception
1515        thread = new Thread(testRoot, null, "no-op thread") {
1516            @Override
1517            public void run() {
1518                throw new TestException();
1519            }
1520        };
1521        thread.start();
1522        try {
1523            thread.join();
1524        } catch (InterruptedException ie) {
1525            fail("Should not have been interrupted");
1526        }
1527        testRoot.destroy();
1528        assertTrue(
1529                "Any thread should notify its ThreadGroup about an uncaught exception:"
1530                        + testRoot, passed[TEST_OTHER]);
1531        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1532        // - - - - - - -
1533
1534        // Our own uncaught exception class
1535        class UncaughtException extends TestException {
1536            private static final long serialVersionUID = 1L;
1537        }
1538
1539        testRoot = new ThreadGroup(originalCurrent,
1540                "Test Exception in uncaught exception") {
1541            @Override
1542            public void uncaughtException(Thread t, Throwable e) {
1543                if (e instanceof TestException) {
1544                    passed[TEST_EXCEPTION_IN_UNCAUGHT] = true;
1545                    // Let's simulate an error inside our uncaughtException
1546                    // method.
1547                    // This should be no-op according to the spec
1548                    throw new UncaughtException();
1549                }
1550                // only forward exceptions other than our test
1551                super.uncaughtException(t, e);
1552            }
1553        };
1554
1555        // Test if an Exception in uncaughtException is really a no-op
1556        thread = new Thread(testRoot, null, "no-op thread") {
1557            @Override
1558            public void run() {
1559                try {
1560                    throw new TestException();
1561                } catch (UncaughtException ue) {
1562                    // any exception in my ThreadGroup's uncaughtException must
1563                    // not be propagated.
1564                    // If it gets propagated and we detected that, the test failed
1565                    passed[TEST_EXCEPTION_IN_UNCAUGHT] = false;
1566                }
1567            }
1568        };
1569        thread.start();
1570        try {
1571            thread.join();
1572        } catch (InterruptedException ie) {
1573            fail("Should not have been interrupted");
1574        }
1575        testRoot.destroy();
1576        assertTrue(
1577                "Any uncaughtException in uncaughtException should be no-op:"
1578                        + testRoot, passed[TEST_EXCEPTION_IN_UNCAUGHT]);
1579        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1580        // - - - - - - -
1581
1582        // This is a mix of 2 of the tests above. It is assumed that ThreadDeath
1583        // and any random exception do work , tested separately. Now we test
1584        // if after an uncaughtException is forwarded to the ThreadGroup and
1585        // the Thread dies, if ThreadDeath is also forwarded. It should be
1586        // (so that a ThreadGroup can know its Thread died)
1587        testRoot = new ThreadGroup(originalCurrent,
1588                "Test Uncaught followed by ThreadDeath") {
1589            @Override
1590            public void uncaughtException(Thread t, Throwable e) {
1591                if (e instanceof ThreadDeath) {
1592                    passed[TEST_DEATH_AFTER_UNCAUGHT] = true;
1593                }
1594                if (e instanceof TestException) {
1595                    passed[TEST_OTHER_THEN_DEATH] = true;
1596                } else {
1597                    // only forward exceptions other than our test
1598                    super.uncaughtException(t, e);
1599                }
1600            }
1601        };
1602
1603        // Test if a Thread tells its ThreadGroup about an Exception and also
1604        // ThreadDeath
1605        thread = new Thread(testRoot, null, "no-op thread") {
1606            @Override
1607            public void run() {
1608                throw new TestException();
1609            }
1610        };
1611        thread.start();
1612        try {
1613            thread.join();
1614        } catch (InterruptedException ie) {
1615            fail("Should not have been interrupted");
1616        }
1617        testRoot.destroy();
1618    }
1619
1620    /*
1621     * @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable)
1622     */
1623    public void uncaughtException(Thread t, Throwable e) {
1624        interrupted = true;
1625        Thread.setDefaultUncaughtExceptionHandler(null);
1626    }
1627
1628    @Override
1629    protected void setUp() {
1630        initialThreadGroup = Thread.currentThread().getThreadGroup();
1631        rootThreadGroup = initialThreadGroup;
1632        while (rootThreadGroup.getParent() != null) {
1633            rootThreadGroup = rootThreadGroup.getParent();
1634        }
1635    }
1636
1637    @Override
1638    protected void tearDown() {
1639        try {
1640            // Give the threads a chance to die.
1641            Thread.sleep(50);
1642        } catch (InterruptedException e) {
1643        }
1644    }
1645
1646    private Thread[] threads(ThreadGroup parent) {
1647        // No API to get the count of immediate children only ?
1648        int count = parent.activeCount();
1649        Thread[] all = new Thread[count];
1650        int actualSize = parent.enumerate(all, false);
1651        Thread[] result;
1652        if (actualSize == all.length) {
1653            result = all;
1654        } else {
1655            result = new Thread[actualSize];
1656            System.arraycopy(all, 0, result, 0, actualSize);
1657        }
1658
1659        return result;
1660
1661    }
1662
1663    private ThreadGroup getInitialThreadGroup() {
1664        return initialThreadGroup;
1665    }
1666
1667    private ThreadGroup[] allGroups(ThreadGroup parent) {
1668        int count = parent.activeGroupCount();
1669        ThreadGroup[] all = new ThreadGroup[count];
1670        parent.enumerate(all, true);
1671        return all;
1672    }
1673
1674    private void daemonTests() {
1675        // Test for method void java.lang.ThreadGroup.setDaemon(boolean)
1676
1677        final ThreadGroup originalCurrent = getInitialThreadGroup();
1678        final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
1679                "Test group");
1680
1681        testRoot.setDaemon(true);
1682        assertTrue("Setting daemon&getting does not work", testRoot.isDaemon());
1683
1684        testRoot.setDaemon(false);
1685        assertTrue("Setting daemon&getting does not work", !testRoot.isDaemon());
1686
1687        testRoot.destroy();
1688    }
1689
1690    private boolean wipeAllThreads(final ThreadGroup aGroup) {
1691        boolean ok = true;
1692        Thread[] threads = threads(aGroup);
1693        for (Thread t : threads) {
1694            ok = ok && wipeThread(t);
1695        }
1696
1697        // Recursively for subgroups (if any)
1698        ThreadGroup[] children = groups(aGroup);
1699        for (ThreadGroup element : children) {
1700            ok = ok && wipeAllThreads(element);
1701        }
1702        return ok;
1703    }
1704
1705    private boolean wipeSideEffectThreads(ThreadGroup aGroup) {
1706        boolean ok = true;
1707        Thread[] threads = threads(aGroup);
1708        for (Thread t : threads) {
1709            if (t.getName().equals("SimpleThread")
1710                    || t.getName().equals("Bogus Name")
1711                    || t.getName().equals("Testing")
1712                    || t.getName().equals("foo")
1713                    || t.getName().equals("Test Group")
1714                    || t.getName().equals("Squawk")
1715                    || t.getName().equals("Thread-1")
1716                    || t.getName().equals("firstOne")
1717                    || t.getName().equals("secondOne")
1718                    || t.getName().equals("Thread-16")
1719                    || t.getName().equals("Thread-14")) {
1720                ok = ok && wipeThread(t);
1721            }
1722        }
1723
1724        // Recursively for subgroups (if any)
1725        ThreadGroup[] children = groups(aGroup);
1726
1727        for (ThreadGroup element : children) {
1728            ok = ok && wipeSideEffectThreads(element);
1729            if(element.getName() !=  null) {
1730                if (element.getName().equals("Test Group")
1731                    || element.getName().equals("foo")
1732                    || element.getName().equals("jp")) {
1733                    element.destroy();
1734                }
1735            }
1736        }
1737        try {
1738            // Give the threads a chance to die.
1739            Thread.sleep(50);
1740        } catch (InterruptedException e) {
1741        }
1742        return ok;
1743    }
1744
1745    private void asyncBuildRandomTreeUnder(final ThreadGroup aGroup,
1746            final int depth, final Vector<ThreadGroup> allCreated) {
1747        if (depth <= 0) {
1748            return;
1749        }
1750
1751        final int maxImmediateSubgroups = random(3);
1752        for (int i = 0; i < maxImmediateSubgroups; i++) {
1753            final int iClone = i;
1754            final String name = " Depth = " + depth + ",N = " + iClone
1755                    + ",Vector size at creation: " + allCreated.size();
1756            // Use concurrency to maximize chance of exposing concurrency bugs
1757            // in ThreadGroups
1758            Thread t = new Thread(aGroup, name) {
1759                @Override
1760                public void run() {
1761                    ThreadGroup newGroup = new ThreadGroup(aGroup, name);
1762                    allCreated.addElement(newGroup);
1763                    asyncBuildRandomTreeUnder(newGroup, depth - 1, allCreated);
1764                }
1765            };
1766            t.start();
1767        }
1768
1769    }
1770
1771    private Vector<ThreadGroup> asyncBuildRandomTreeUnder(final ThreadGroup aGroup,
1772            final int depth) {
1773        Vector<ThreadGroup> result = new Vector<ThreadGroup>();
1774        asyncBuildRandomTreeUnder(aGroup, depth, result);
1775        return result;
1776
1777    }
1778
1779    private boolean allSuspended(Vector<MyThread> threads) {
1780        for (int i = 0; i < threads.size(); i++) {
1781            MyThread t = threads.elementAt(i);
1782            if (t.isActivelyRunning()) {
1783                return false;
1784            }
1785        }
1786
1787        return true;
1788
1789    }
1790
1791    private ThreadGroup[] groups(ThreadGroup parent) {
1792        // No API to get the count of immediate children only ?
1793        int count = parent.activeGroupCount();
1794        ThreadGroup[] all = new ThreadGroup[count];
1795        parent.enumerate(all, false);
1796        // Now we may have nulls in the array, we must find the actual size
1797        int actualSize = 0;
1798        for (; actualSize < all.length; actualSize++) {
1799            if (all[actualSize] == null) {
1800                break;
1801            }
1802        }
1803        ThreadGroup[] result;
1804        if (actualSize == all.length) {
1805            result = all;
1806        } else {
1807            result = new ThreadGroup[actualSize];
1808            System.arraycopy(all, 0, result, 0, actualSize);
1809        }
1810
1811        return result;
1812
1813    }
1814
1815    private Vector<MyThread> populateGroupsWithThreads(final ThreadGroup aGroup,
1816            final int threadCount) {
1817        Vector<MyThread> result = new Vector<MyThread>();
1818        populateGroupsWithThreads(aGroup, threadCount, result);
1819        return result;
1820
1821    }
1822
1823    private void populateGroupsWithThreads(final ThreadGroup aGroup,
1824            final int threadCount, final Vector<MyThread> allCreated) {
1825        for (int i = 0; i < threadCount; i++) {
1826            final int iClone = i;
1827            final String name = "(MyThread)N =" + iClone + "/" + threadCount
1828                    + " ,Vector size at creation: " + allCreated.size();
1829
1830            MyThread t = new MyThread(aGroup, name);
1831            allCreated.addElement(t);
1832        }
1833
1834        // Recursively for subgroups (if any)
1835        ThreadGroup[] children = groups(aGroup);
1836        for (ThreadGroup element : children) {
1837            populateGroupsWithThreads(element, threadCount, allCreated);
1838        }
1839
1840    }
1841
1842    private int random(int max) {
1843
1844        return 1 + ((new Object()).hashCode() % max);
1845
1846    }
1847
1848    @SuppressWarnings("deprecation")
1849    private boolean wipeThread(Thread t) {
1850        t.stop();
1851        try {
1852            t.join(1000);
1853        } catch (InterruptedException ie) {
1854            fail("Should not have been interrupted");
1855        }
1856        // The thread had plenty (subjective) of time to die so there
1857        // is a problem.
1858        if (t.isAlive()) {
1859            return false;
1860        }
1861
1862        return true;
1863    }
1864
1865    private Vector<ThreadGroup> buildRandomTreeUnder(ThreadGroup aGroup, int depth) {
1866        Vector<ThreadGroup> result = asyncBuildRandomTreeUnder(aGroup, depth);
1867        while (true) {
1868            int sizeBefore = result.size();
1869            try {
1870                Thread.sleep(1000);
1871                int sizeAfter = result.size();
1872                // If no activity for a while, we assume async building may be
1873                // done.
1874                if (sizeBefore == sizeAfter) {
1875                    // It can only be done if no more threads. Unfortunately we
1876                    // are relying on this API to work as well.
1877                    // If it does not, we may loop forever.
1878                    if (aGroup.activeCount() == 0) {
1879                        break;
1880                    }
1881                }
1882            } catch (InterruptedException e) {
1883            }
1884        }
1885        return result;
1886
1887    }
1888
1889    private boolean arrayIncludes(Object[] array, Object toTest) {
1890        for (Object element : array) {
1891            if (element == toTest) {
1892                return true;
1893            }
1894        }
1895
1896        return false;
1897    }
1898
1899    protected void myassertTrue(String msg, boolean b) {
1900        // This method is defined here just to solve a visibility problem
1901        // of protected methods with inner types
1902        assertTrue(msg, b);
1903    }
1904
1905    private ThreadGroup getRootThreadGroup() {
1906        return rootThreadGroup;
1907
1908    }
1909
1910    SecurityManager sm = new SecurityManager() {
1911
1912        public void checkPermission(Permission perm) {
1913        }
1914
1915        public void checkAccess(ThreadGroup g) {
1916           throw new SecurityException();
1917        }
1918    };
1919}
1920