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