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