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