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