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