0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.harmony.luni.tests.java.lang;
0019:
0020: import java.util.Vector;
0021:
0022: public class ThreadGroupTest extends junit.framework.TestCase {
0023:
0024: class MyThread extends Thread {
0025: public volatile int heartBeat = 0;
0026:
0027: public MyThread(ThreadGroup group, String name)
0028: throws SecurityException, IllegalThreadStateException {
0029: super (group, name);
0030: }
0031:
0032: @Override
0033: public void run() {
0034: while (true) {
0035: heartBeat++;
0036: try {
0037: Thread.sleep(50);
0038: } catch (InterruptedException e) {
0039: }
0040: }
0041: }
0042:
0043: public boolean isActivelyRunning() {
0044: long MAX_WAIT = 100;
0045: return isActivelyRunning(MAX_WAIT);
0046: }
0047:
0048: public boolean isActivelyRunning(long maxWait) {
0049: int beat = heartBeat;
0050: long start = System.currentTimeMillis();
0051: do {
0052: Thread.yield();
0053: int beat2 = heartBeat;
0054: if (beat != beat2) {
0055: return true;
0056: }
0057: } while (System.currentTimeMillis() - start < maxWait);
0058: return false;
0059: }
0060:
0061: }
0062:
0063: private ThreadGroup rootThreadGroup = null;
0064:
0065: private ThreadGroup initialThreadGroup = null;
0066:
0067: /**
0068: * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.String)
0069: */
0070: public void test_ConstructorLjava_lang_String() {
0071: // Test for method java.lang.ThreadGroup(java.lang.String)
0072:
0073: // Unfortunately we have to use other APIs as well as we test the
0074: // constructor
0075:
0076: ThreadGroup newGroup = null;
0077: ThreadGroup initial = getInitialThreadGroup();
0078: final String name = "Test name";
0079: newGroup = new ThreadGroup(name);
0080: assertTrue(
0081: "Has to be possible to create a subgroup of current group using simple constructor",
0082: newGroup.getParent() == initial);
0083: assertTrue("Name has to be correct", newGroup.getName().equals(
0084: name));
0085:
0086: // cleanup
0087: newGroup.destroy();
0088:
0089: }
0090:
0091: /**
0092: * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.ThreadGroup,
0093: * java.lang.String)
0094: */
0095: public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_String() {
0096: // Test for method java.lang.ThreadGroup(java.lang.ThreadGroup,
0097: // java.lang.String)
0098:
0099: // Unfortunately we have to use other APIs as well as we test the
0100: // constructor
0101:
0102: ThreadGroup newGroup = null;
0103:
0104: try {
0105: newGroup = new ThreadGroup(null, null);
0106: } catch (NullPointerException e) {
0107: }
0108: assertNull("Can't create a ThreadGroup with a null parent",
0109: newGroup);
0110:
0111: newGroup = new ThreadGroup(getInitialThreadGroup(), null);
0112: assertTrue(
0113: "Has to be possible to create a subgroup of current group",
0114: newGroup.getParent() == Thread.currentThread()
0115: .getThreadGroup());
0116:
0117: // Lets start all over
0118: newGroup.destroy();
0119:
0120: newGroup = new ThreadGroup(getRootThreadGroup(), "a name here");
0121: assertTrue(
0122: "Has to be possible to create a subgroup of root group",
0123: newGroup.getParent() == getRootThreadGroup());
0124:
0125: // Lets start all over
0126: newGroup.destroy();
0127:
0128: try {
0129: newGroup = new ThreadGroup(newGroup, "a name here");
0130: } catch (IllegalThreadStateException e) {
0131: newGroup = null;
0132: }
0133: ;
0134: assertNull("Can't create a subgroup of a destroyed group",
0135: newGroup);
0136: }
0137:
0138: /**
0139: * @tests java.lang.ThreadGroup#activeCount()
0140: */
0141: public void test_activeCount() {
0142: // Test for method int java.lang.ThreadGroup.activeCount()
0143: ThreadGroup tg = new ThreadGroup("activeCount");
0144: Thread t1 = new Thread(tg, new Runnable() {
0145: public void run() {
0146: try {
0147: Thread.sleep(5000);
0148: } catch (InterruptedException e) {
0149: }
0150: }
0151: });
0152: int count = tg.activeCount();
0153: assertTrue("wrong active count: " + count, count == 0);
0154: t1.start();
0155: count = tg.activeCount();
0156: assertTrue("wrong active count: " + count, count == 1);
0157: t1.interrupt();
0158: try {
0159: t1.join();
0160: } catch (InterruptedException e) {
0161: }
0162: // cleanup
0163: tg.destroy();
0164: }
0165:
0166: /**
0167: * @tests java.lang.ThreadGroup#checkAccess()
0168: */
0169: public void test_checkAccess() {
0170: // Test for method void java.lang.ThreadGroup.checkAccess()
0171:
0172: final ThreadGroup originalCurrent = getInitialThreadGroup();
0173: ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0174: "Test group");
0175:
0176: SecurityManager currentManager = System.getSecurityManager();
0177: boolean passed = true;
0178:
0179: try {
0180: if (currentManager != null) {
0181: testRoot.checkAccess();
0182: }
0183: } catch (SecurityException se) {
0184: passed = false;
0185: }
0186:
0187: assertTrue("CheckAccess is no-op with no SecurityManager",
0188: passed);
0189:
0190: testRoot.destroy();
0191:
0192: }
0193:
0194: /**
0195: * @tests java.lang.ThreadGroup#destroy()
0196: */
0197: public void test_destroy() {
0198: // Test for method void java.lang.ThreadGroup.destroy()
0199:
0200: final ThreadGroup originalCurrent = getInitialThreadGroup();
0201: ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0202: "Test group");
0203: final int DEPTH = 4;
0204: final Vector<ThreadGroup> subgroups = buildRandomTreeUnder(
0205: testRoot, DEPTH);
0206:
0207: // destroy them all
0208: testRoot.destroy();
0209:
0210: for (int i = 0; i < subgroups.size(); i++) {
0211: ThreadGroup child = subgroups.elementAt(i);
0212: assertEquals("Destroyed child can't have children", 0,
0213: child.activeCount());
0214: boolean passed = false;
0215: try {
0216: child.destroy();
0217: } catch (IllegalThreadStateException e) {
0218: passed = true;
0219: }
0220: ;
0221: assertTrue("Destroyed child can't be destroyed again",
0222: passed);
0223: }
0224:
0225: testRoot = new ThreadGroup(originalCurrent,
0226: "Test group (daemon)");
0227: testRoot.setDaemon(true);
0228:
0229: ThreadGroup child = new ThreadGroup(testRoot, "daemon child");
0230:
0231: // If we destroy the last daemon's child, the daemon should get destroyed
0232: // as well
0233: child.destroy();
0234:
0235: boolean passed = false;
0236: try {
0237: child.destroy();
0238: } catch (IllegalThreadStateException e) {
0239: passed = true;
0240: }
0241: ;
0242: assertTrue("Daemon should have been destroyed already", passed);
0243:
0244: passed = false;
0245: try {
0246: testRoot.destroy();
0247: } catch (IllegalThreadStateException e) {
0248: passed = true;
0249: }
0250: ;
0251: assertTrue(
0252: "Daemon parent should have been destroyed automatically",
0253: passed);
0254:
0255: assertTrue(
0256: "Destroyed daemon's child should not be in daemon's list anymore",
0257: !arrayIncludes(groups(testRoot), child));
0258: assertTrue(
0259: "Destroyed daemon should not be in parent's list anymore",
0260: !arrayIncludes(groups(originalCurrent), testRoot));
0261:
0262: testRoot = new ThreadGroup(originalCurrent,
0263: "Test group (daemon)");
0264: testRoot.setDaemon(true);
0265: Thread noOp = new Thread(testRoot, null, "no-op thread") {
0266: @Override
0267: public void run() {
0268: }
0269: };
0270: noOp.start();
0271:
0272: // Wait for the no-op thread to run inside daemon ThreadGroup
0273: try {
0274: noOp.join();
0275: } catch (InterruptedException ie) {
0276: fail("Should not be interrupted");
0277: }
0278: ;
0279:
0280: passed = false;
0281: try {
0282: child.destroy();
0283: } catch (IllegalThreadStateException e) {
0284: passed = true;
0285: }
0286: ;
0287: assertTrue(
0288: "Daemon group should have been destroyed already when last thread died",
0289: passed);
0290:
0291: testRoot = new ThreadGroup(originalCurrent,
0292: "Test group (daemon)");
0293: noOp = new Thread(testRoot, null, "no-op thread") {
0294: @Override
0295: public void run() {
0296: try {
0297: Thread.sleep(500);
0298: } catch (InterruptedException ie) {
0299: fail("Should not be interrupted");
0300: }
0301: }
0302: };
0303:
0304: // Has to execute the next lines in an interval < the sleep interval of
0305: // the no-op thread
0306: noOp.start();
0307: passed = false;
0308: try {
0309: testRoot.destroy();
0310: } catch (IllegalThreadStateException its) {
0311: passed = true;
0312: }
0313: assertTrue("Can't destroy a ThreadGroup that has threads",
0314: passed);
0315:
0316: // But after the thread dies, we have to be able to destroy the thread
0317: // group
0318: try {
0319: noOp.join();
0320: } catch (InterruptedException ie) {
0321: fail("Should not be interrupted");
0322: }
0323: ;
0324: passed = true;
0325: try {
0326: testRoot.destroy();
0327: } catch (IllegalThreadStateException its) {
0328: passed = false;
0329: }
0330: assertTrue(
0331: "Should be able to destroy a ThreadGroup that has no threads",
0332: passed);
0333:
0334: }
0335:
0336: /**
0337: * @tests java.lang.ThreadGroup#destroy()
0338: */
0339: public void test_destroy_subtest0() {
0340: ThreadGroup group1 = new ThreadGroup("test_destroy_subtest0");
0341: group1.destroy();
0342: try {
0343: new Thread(group1, "test_destroy_subtest0");
0344: fail("should throw IllegalThreadStateException");
0345: } catch (IllegalThreadStateException e) {
0346: }
0347: }
0348:
0349: /**
0350: * @tests java.lang.ThreadGroup#getMaxPriority()
0351: */
0352: public void test_getMaxPriority() {
0353: // Test for method int java.lang.ThreadGroup.getMaxPriority()
0354:
0355: final ThreadGroup originalCurrent = getInitialThreadGroup();
0356: ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0357: "Test group");
0358:
0359: boolean passed = true;
0360: try {
0361: testRoot.setMaxPriority(Thread.MIN_PRIORITY);
0362: } catch (IllegalArgumentException iae) {
0363: passed = false;
0364: }
0365: assertTrue("Should be able to set priority", passed);
0366:
0367: assertTrue("New value should be the same as we set", testRoot
0368: .getMaxPriority() == Thread.MIN_PRIORITY);
0369:
0370: testRoot.destroy();
0371:
0372: }
0373:
0374: /**
0375: * @tests java.lang.ThreadGroup#getName()
0376: */
0377: public void test_getName() {
0378: // Test for method java.lang.String java.lang.ThreadGroup.getName()
0379:
0380: final ThreadGroup originalCurrent = getInitialThreadGroup();
0381: final String name = "Test group";
0382: final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0383: name);
0384:
0385: assertTrue("Setting a name&getting does not work", testRoot
0386: .getName().equals(name));
0387:
0388: testRoot.destroy();
0389:
0390: }
0391:
0392: /**
0393: * @tests java.lang.ThreadGroup#getParent()
0394: */
0395: public void test_getParent() {
0396: // Test for method java.lang.ThreadGroup
0397: // java.lang.ThreadGroup.getParent()
0398:
0399: final ThreadGroup originalCurrent = getInitialThreadGroup();
0400: ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0401: "Test group");
0402:
0403: assertTrue("Parent is wrong",
0404: testRoot.getParent() == originalCurrent);
0405:
0406: // Create some groups, nested some levels.
0407: final int TOTAL_DEPTH = 5;
0408: ThreadGroup current = testRoot;
0409: Vector<ThreadGroup> groups = new Vector<ThreadGroup>();
0410: // To maintain the invariant that a thread in the Vector is parent
0411: // of the next one in the collection (and child of the previous one)
0412: groups.addElement(testRoot);
0413:
0414: for (int i = 0; i < TOTAL_DEPTH; i++) {
0415: current = new ThreadGroup(current, "level " + i);
0416: groups.addElement(current);
0417: }
0418:
0419: // Now we walk the levels down, checking if parent is ok
0420: for (int i = 1; i < groups.size(); i++) {
0421: current = groups.elementAt(i);
0422: ThreadGroup previous = groups.elementAt(i - 1);
0423: assertTrue("Parent is wrong",
0424: current.getParent() == previous);
0425: }
0426:
0427: final ThreadGroup[] checkAccessGroup = new ThreadGroup[1];
0428: class SecurityManagerImpl extends MutableSecurityManager {
0429: @Override
0430: public void checkAccess(ThreadGroup group) {
0431: checkAccessGroup[0] = group;
0432: }
0433: }
0434: SecurityManagerImpl sm = new SecurityManagerImpl();
0435: //add permission to allow reset of security manager
0436: sm.addPermission(MutableSecurityManager.SET_SECURITY_MANAGER);
0437:
0438: ThreadGroup parent;
0439: try {
0440: // To see if it checks Thread creation with our SecurityManager
0441: System.setSecurityManager(sm);
0442: parent = testRoot.getParent();
0443: } finally {
0444: // restore original, no side-effects
0445: System.setSecurityManager(null);
0446: }
0447: assertTrue("checkAccess with incorrect group",
0448: checkAccessGroup[0] == parent);
0449:
0450: testRoot.destroy();
0451: }
0452:
0453: /**
0454: * @tests java.lang.ThreadGroup#isDaemon()
0455: */
0456: public void test_isDaemon() {
0457: // Test for method boolean java.lang.ThreadGroup.isDaemon()
0458:
0459: daemonTests();
0460:
0461: }
0462:
0463: /**
0464: * @tests java.lang.ThreadGroup#list()
0465: */
0466: public void test_list() {
0467: // Test for method void java.lang.ThreadGroup.list()
0468:
0469: final ThreadGroup originalCurrent = getInitialThreadGroup();
0470: // wipeSideEffectThreads destroy all side effect of threads created in
0471: // java.lang.Thread
0472: boolean result = wipeSideEffectThreads(originalCurrent);
0473: if (result == false) {
0474: fail("wipe threads in test_list() not successful");
0475: }
0476: final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0477: "Test group");
0478:
0479: // First save the original System.out
0480: java.io.PrintStream originalOut = System.out;
0481:
0482: try {
0483: java.io.ByteArrayOutputStream contentsStream = new java.io.ByteArrayOutputStream(
0484: 100);
0485: java.io.PrintStream newOut = new java.io.PrintStream(
0486: contentsStream);
0487:
0488: // We have to "redirect" System.out to test the method 'list'
0489: System.setOut(newOut);
0490:
0491: originalCurrent.list();
0492:
0493: /*
0494: * The output has to look like this
0495: *
0496: * java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main]
0497: * java.lang.ThreadGroup[name=Test group,maxpri=10]
0498: *
0499: */
0500:
0501: String contents = new String(contentsStream.toByteArray());
0502: boolean passed = (contents.indexOf("ThreadGroup[name=main") != -1)
0503: && (contents.indexOf("Thread[") != -1)
0504: && (contents.indexOf("ThreadGroup[name=Test group") != -1);
0505: assertTrue("'list()' does not print expected contents. "
0506: + "Result from list: " + contents, passed);
0507: // Do proper cleanup
0508: testRoot.destroy();
0509:
0510: } finally {
0511: // No matter what, we need to restore the original System.out
0512: System.setOut(originalOut);
0513: }
0514:
0515: }
0516:
0517: /**
0518: * @tests java.lang.ThreadGroup#parentOf(java.lang.ThreadGroup)
0519: */
0520: public void test_parentOfLjava_lang_ThreadGroup() {
0521: // Test for method boolean
0522: // java.lang.ThreadGroup.parentOf(java.lang.ThreadGroup)
0523:
0524: final ThreadGroup originalCurrent = getInitialThreadGroup();
0525: final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0526: "Test group");
0527: final int DEPTH = 4;
0528: buildRandomTreeUnder(testRoot, DEPTH);
0529:
0530: final ThreadGroup[] allChildren = allGroups(testRoot);
0531: for (ThreadGroup element : allChildren) {
0532: assertTrue("Have to be parentOf all children", testRoot
0533: .parentOf(element));
0534: }
0535:
0536: assertTrue("Have to be parentOf itself", testRoot
0537: .parentOf(testRoot));
0538:
0539: testRoot.destroy();
0540: assertTrue("Parent can't have test group as subgroup anymore",
0541: !arrayIncludes(groups(testRoot.getParent()), testRoot));
0542:
0543: try {
0544: System.setSecurityManager(new MutableSecurityManager(
0545: MutableSecurityManager.SET_SECURITY_MANAGER));
0546: assertTrue("Should not be parent", !testRoot
0547: .parentOf(originalCurrent));
0548: } finally {
0549: System.setSecurityManager(null);
0550: }
0551: }
0552:
0553: /**
0554: * @tests java.lang.ThreadGroup#resume()
0555: */
0556: @SuppressWarnings("deprecation")
0557: public void test_resume() throws OutOfMemoryError {
0558: // Test for method void java.lang.ThreadGroup.resume()
0559:
0560: final ThreadGroup originalCurrent = getInitialThreadGroup();
0561:
0562: final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0563: "Test group");
0564: final int DEPTH = 2;
0565: buildRandomTreeUnder(testRoot, DEPTH);
0566:
0567: final int THREADS_PER_GROUP = 2;
0568: final Vector<MyThread> threads = populateGroupsWithThreads(
0569: testRoot, THREADS_PER_GROUP);
0570:
0571: boolean[] isResumed = null;
0572: try {
0573: try {
0574: for (int i = 0; i < threads.size(); i++) {
0575: Thread t = threads.elementAt(i);
0576: t.start();
0577: t.suspend();
0578: }
0579: // In 5.0, activeCount() only returns threads that are alive
0580: assertTrue(
0581: "Internal error when populating ThreadGroups",
0582: testRoot.activeCount() == threads.size());
0583: } catch (OutOfMemoryError e) {
0584: for (int i = 0; i < threads.size(); i++) {
0585: Thread t = threads.elementAt(i);
0586: t.resume();
0587: t.stop(); // deprecated but effective
0588: }
0589: throw e;
0590: }
0591:
0592: // Now that they are all suspended, let's resume the ThreadGroup
0593: testRoot.resume();
0594:
0595: // Give them some time to really resume
0596: try {
0597: Thread.sleep(500);
0598: } catch (InterruptedException ie) {
0599: fail("Should not have been interrupted");
0600: }
0601:
0602: isResumed = new boolean[threads.size()];
0603: boolean failed = false;
0604: for (int i = 0; i < isResumed.length; i++) {
0605: MyThread t = threads.elementAt(i);
0606: if (!failed) { // if one failed, don't waste time checking the
0607: // rest
0608: isResumed[i] = t.isActivelyRunning(1000);
0609: failed = failed | (!isResumed[i]);
0610: }
0611: t.stop(); // deprecated but effective
0612: }
0613:
0614: // Give them some time to really die
0615: try {
0616: Thread.sleep(500);
0617: } catch (InterruptedException ie) {
0618: fail("Should not have been interrupted");
0619: }
0620: } finally {
0621: // Make sure we do cleanup before returning
0622: testRoot.destroy();
0623: }
0624:
0625: for (int i = 0; i < isResumed.length; i++) {
0626: assertTrue("Thread " + threads.elementAt(i)
0627: + " was not running when it was killed",
0628: isResumed[i]);
0629: }
0630:
0631: assertEquals("Method destroy must have problems", 0, testRoot
0632: .activeCount());
0633:
0634: }
0635:
0636: /**
0637: * @tests java.lang.ThreadGroup#setDaemon(boolean)
0638: */
0639: public void test_setDaemonZ() {
0640: // Test for method void java.lang.ThreadGroup.setDaemon(boolean)
0641:
0642: daemonTests();
0643:
0644: }
0645:
0646: /**
0647: * @tests java.lang.ThreadGroup#setMaxPriority(int)
0648: */
0649: public void test_setMaxPriorityI() {
0650: // Test for method void java.lang.ThreadGroup.setMaxPriority(int)
0651:
0652: final ThreadGroup originalCurrent = getInitialThreadGroup();
0653: ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0654: "Test group");
0655:
0656: boolean passed;
0657:
0658: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0659:
0660: int currentMax = testRoot.getMaxPriority();
0661: testRoot.setMaxPriority(Thread.MAX_PRIORITY + 1);
0662: passed = testRoot.getMaxPriority() == currentMax;
0663: assertTrue(
0664: "setMaxPriority: Any value higher than the current one is ignored. Before: "
0665: + currentMax + " , after: "
0666: + testRoot.getMaxPriority(), passed);
0667:
0668: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0669:
0670: currentMax = testRoot.getMaxPriority();
0671: testRoot.setMaxPriority(Thread.MIN_PRIORITY - 1);
0672: passed = testRoot.getMaxPriority() == Thread.MIN_PRIORITY;
0673: assertTrue(
0674: "setMaxPriority: Any value smaller than MIN_PRIORITY is adjusted to MIN_PRIORITY. Before: "
0675: + currentMax
0676: + " , after: "
0677: + testRoot.getMaxPriority(), passed);
0678:
0679: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0680:
0681: testRoot.destroy();
0682: testRoot = new ThreadGroup(originalCurrent, "Test group");
0683:
0684: // Create some groups, nested some levels. Each level will have maxPrio
0685: // 1 unit smaller than the parent's. However, there can't be a group
0686: // with priority < Thread.MIN_PRIORITY
0687: final int TOTAL_DEPTH = testRoot.getMaxPriority()
0688: - Thread.MIN_PRIORITY - 2;
0689: ThreadGroup current = testRoot;
0690: for (int i = 0; i < TOTAL_DEPTH; i++) {
0691: current = new ThreadGroup(current, "level " + i);
0692: }
0693:
0694: // Now we walk the levels down, changing the maxPrio and later verifying
0695: // that the value is indeed 1 unit smaller than the parent's maxPrio.
0696: int maxPrio, parentMaxPrio;
0697: current = testRoot;
0698:
0699: // To maintain the invariant that when we are to modify a child,
0700: // its maxPriority is always 1 unit smaller than its parent's.
0701: // We have to set it for the root manually, and the loop does the rest
0702: // for all the other sub-levels
0703: current
0704: .setMaxPriority(current.getParent().getMaxPriority() - 1);
0705:
0706: for (int i = 0; i < TOTAL_DEPTH; i++) {
0707: maxPrio = current.getMaxPriority();
0708: parentMaxPrio = current.getParent().getMaxPriority();
0709:
0710: ThreadGroup[] children = groups(current);
0711: assertEquals("Can only have 1 subgroup", 1, children.length);
0712: current = children[0];
0713: assertTrue(
0714: "Had to be 1 unit smaller than parent's priority in iteration="
0715: + i + " checking->" + current,
0716: maxPrio == parentMaxPrio - 1);
0717: current.setMaxPriority(maxPrio - 1);
0718:
0719: // The next test is sort of redundant, since in next iteration it
0720: // will be the parent tGroup, so the test will be done.
0721: assertTrue("Had to be possible to change max priority",
0722: current.getMaxPriority() == maxPrio - 1);
0723: }
0724:
0725: assertTrue(
0726: "Priority of leaf child group has to be much smaller than original root group",
0727: current.getMaxPriority() == testRoot.getMaxPriority()
0728: - TOTAL_DEPTH);
0729:
0730: testRoot.destroy();
0731:
0732: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0733:
0734: passed = true;
0735: testRoot = new ThreadGroup(originalCurrent, "Test group");
0736: try {
0737: testRoot.setMaxPriority(Thread.MAX_PRIORITY);
0738: } catch (IllegalArgumentException iae) {
0739: passed = false;
0740: }
0741: assertTrue(
0742: "Max Priority = Thread.MAX_PRIORITY should be possible if the test is run with default system ThreadGroup as root",
0743: passed);
0744: testRoot.destroy();
0745:
0746: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0747:
0748: passed = true;
0749: testRoot = new ThreadGroup(originalCurrent, "Test group");
0750: System.setSecurityManager(new MutableSecurityManager(
0751: MutableSecurityManager.SET_SECURITY_MANAGER));
0752: try {
0753: try {
0754: testRoot.setMaxPriority(Thread.MIN_PRIORITY);
0755: } catch (IllegalArgumentException iae) {
0756: passed = false;
0757: }
0758: } finally {
0759: System.setSecurityManager(null);
0760: }
0761: assertTrue(
0762: "Min Priority = Thread.MIN_PRIORITY should be possible, always",
0763: passed);
0764: testRoot.destroy();
0765:
0766: try {
0767: System.setSecurityManager(new MutableSecurityManager(
0768: MutableSecurityManager.SET_SECURITY_MANAGER));
0769: originalCurrent.setMaxPriority(Thread.MAX_PRIORITY);
0770: } finally {
0771: System.setSecurityManager(null);
0772: }
0773: }
0774:
0775: /**
0776: * @tests java.lang.ThreadGroup#stop()
0777: */
0778: @SuppressWarnings("deprecation")
0779: public void test_stop() throws OutOfMemoryError {
0780: // Test for method void java.lang.ThreadGroup.stop()
0781:
0782: final ThreadGroup originalCurrent = getInitialThreadGroup();
0783:
0784: final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0785: "Test group");
0786: final int DEPTH = 2;
0787: buildRandomTreeUnder(testRoot, DEPTH);
0788:
0789: final int THREADS_PER_GROUP = 2;
0790: final Vector<MyThread> threads = populateGroupsWithThreads(
0791: testRoot, THREADS_PER_GROUP);
0792:
0793: try {
0794: for (int i = 0; i < threads.size(); i++) {
0795: Thread t = threads.elementAt(i);
0796: t.start();
0797: }
0798: } catch (OutOfMemoryError e) {
0799: for (int i = 0; i < threads.size(); i++) {
0800: Thread t = threads.elementAt(i);
0801: t.stop(); // deprecated but effective
0802: }
0803: throw e;
0804: }
0805:
0806: // Now that they are all running, let's stop the ThreadGroup
0807: testRoot.stop();
0808:
0809: // stop is an async call. The thread may take a while to stop. We have
0810: // to wait for all of them to stop. However, if stop does not work,
0811: // we'd have to wait forever. So, we wait with a timeout, and if the
0812: // Thread is still alive, we assume stop for ThreadGroups does not
0813: // work. How much we wait (timeout) is very important
0814: boolean passed = true;
0815: for (int i = 0; i < threads.size(); i++) {
0816: Thread t = threads.elementAt(i);
0817: try {
0818: // We wait 5000 ms per Thread, but due to scheduling it may
0819: // take a while to run
0820: t.join(5000);
0821: } catch (InterruptedException ie) {
0822: fail("Should not be interrupted");
0823: }
0824: if (t.isAlive()) {
0825: passed = false;
0826: break;
0827: }
0828: }
0829:
0830: // To make sure that even if we fail, we exit in a clean state
0831: testRoot.destroy();
0832:
0833: assertTrue("Thread should be dead by now", passed);
0834:
0835: assertEquals(
0836: "Method destroy (or wipeAllThreads) must have problems",
0837: 0, testRoot.activeCount());
0838:
0839: }
0840:
0841: /**
0842: * @tests java.lang.ThreadGroup#suspend()
0843: */
0844: @SuppressWarnings("deprecation")
0845: public void test_suspend() throws OutOfMemoryError {
0846: // Test for method void java.lang.ThreadGroup.suspend()
0847:
0848: final ThreadGroup originalCurrent = getInitialThreadGroup();
0849:
0850: final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
0851: "Test group");
0852: final int DEPTH = 2;
0853: buildRandomTreeUnder(testRoot, DEPTH);
0854:
0855: final int THREADS_PER_GROUP = 2;
0856: final Vector<MyThread> threads = populateGroupsWithThreads(
0857: testRoot, THREADS_PER_GROUP);
0858:
0859: boolean passed = false;
0860: try {
0861: try {
0862: for (int i = 0; i < threads.size(); i++) {
0863: Thread t = threads.elementAt(i);
0864: t.start();
0865: }
0866: } catch (OutOfMemoryError e) {
0867: for (int i = 0; i < threads.size(); i++) {
0868: Thread t = threads.elementAt(i);
0869: t.stop(); // deprecated but effective
0870: }
0871: throw e;
0872: }
0873:
0874: // Now that they are all running, let's suspend the ThreadGroup
0875: testRoot.suspend();
0876:
0877: passed = allSuspended(threads);
0878: assertTrue(
0879: "Should be able to wipe all threads (allSuspended="
0880: + passed + ")", wipeAllThreads(testRoot));
0881: } finally {
0882:
0883: // We can't destroy a ThreadGroup if we do not make sure it has no
0884: // threads at all
0885: testRoot.stop();
0886: long waitTime = 5000;
0887: for (int i = 0; i < threads.size(); i++) {
0888: Thread t = threads.elementAt(i);
0889: while (t.isAlive() && waitTime >= 0) {
0890: try {
0891: Thread.sleep(10);
0892: waitTime -= 10;
0893: } catch (InterruptedException e) {
0894: fail("unexpected interruption");
0895: }
0896: }
0897: if (waitTime < 0) {
0898: fail("stop() has not stopped threads in ThreadGroup 'testRoot'");
0899: }
0900: }
0901: // Make sure we cleanup before returning from the method
0902: testRoot.destroy();
0903: }
0904: assertTrue("All threads should be suspended", passed);
0905:
0906: assertEquals(
0907: "Method destroy (or wipeAllThreads) must have problems",
0908: 0, testRoot.activeCount());
0909:
0910: }
0911:
0912: /**
0913: * @tests java.lang.ThreadGroup#toString()
0914: */
0915: public void test_toString() {
0916: // Test for method java.lang.String java.lang.ThreadGroup.toString()
0917:
0918: final ThreadGroup originalCurrent = getInitialThreadGroup();
0919: final String tGroupName = "Test group";
0920:
0921: // Our own subclass
0922: class MyThreadGroup extends ThreadGroup {
0923: // Have to define a constructor since there's no default one
0924: public MyThreadGroup(ThreadGroup parent, String name) {
0925: super (parent, name);
0926: }
0927: }
0928: ;
0929:
0930: ThreadGroup testRoot = new MyThreadGroup(originalCurrent,
0931: tGroupName);
0932: final String toString = testRoot.toString();
0933:
0934: StringBuffer expectedResult = new StringBuffer();
0935: expectedResult.append(testRoot.getClass().getName());
0936: expectedResult.append("[name=");
0937: expectedResult.append(tGroupName);
0938: expectedResult.append(",maxpri=");
0939: expectedResult.append(testRoot.getMaxPriority());
0940: expectedResult.append("]");
0941:
0942: String expectedValue = expectedResult.toString();
0943:
0944: assertTrue("toString does not follow the Java language spec.",
0945: toString.equals(expectedValue));
0946:
0947: testRoot.destroy();
0948: }
0949:
0950: /**
0951: * @tests java.lang.ThreadGroup#uncaughtException(java.lang.Thread,
0952: * java.lang.Throwable)
0953: */
0954: @SuppressWarnings("deprecation")
0955: public void test_uncaughtExceptionLjava_lang_ThreadLjava_lang_Throwable() {
0956: // Test for method void
0957: // java.lang.ThreadGroup.uncaughtException(java.lang.Thread,
0958: // java.lang.Throwable)
0959:
0960: final ThreadGroup originalCurrent = getInitialThreadGroup();
0961:
0962: // indices for the array defined below
0963: final int TEST_DEATH = 0;
0964: final int TEST_OTHER = 1;
0965: final int TEST_EXCEPTION_IN_UNCAUGHT = 2;
0966: final int TEST_OTHER_THEN_DEATH = 3;
0967: final int TEST_FORCING_THROW_THREAD_DEATH = 4;
0968: final int TEST_KILLING = 5;
0969: final int TEST_DEATH_AFTER_UNCAUGHT = 6;
0970:
0971: final boolean[] passed = new boolean[] { false, false, false,
0972: false, false, false, false };
0973:
0974: ThreadGroup testRoot;
0975: Thread thread;
0976:
0977: // Our own exception class
0978: class TestException extends RuntimeException {
0979: private static final long serialVersionUID = 1L;
0980: }
0981:
0982: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0983: // - - - - - - -
0984: testRoot = new ThreadGroup(originalCurrent,
0985: "Test killing a Thread, forcing it to throw ThreadDeath") {
0986: @Override
0987: public void uncaughtException(Thread t, Throwable e) {
0988: if (e instanceof ThreadDeath) {
0989: passed[TEST_KILLING] = true;
0990: }
0991: // always forward, any exception
0992: super .uncaughtException(t, e);
0993: }
0994: };
0995:
0996: // Test if a Thread tells its ThreadGroup about ThreadDeath
0997: thread = new Thread(testRoot, null,
0998: "victim thread (to be killed)") {
0999: @Override
1000: public void run() {
1001: while (true) {
1002: Thread.yield();
1003: }
1004: }
1005: };
1006: thread.start();
1007: try {
1008: Thread.sleep(1000);
1009: } catch (InterruptedException ie) {
1010: fail("Should not have been interrupted");
1011: }
1012: // we know this is deprecated, but we must test this scenario.
1013: // When we stop a thread, it is tagged as not alive even though it is
1014: // still running code.
1015: // join would be a no-op, and we might have a race condition. So, to
1016: // play safe, we wait before joining & testing if the exception was
1017: // really forwarded to the ThreadGroup
1018: thread.stop();
1019: try {
1020: Thread.sleep(1000);
1021: } catch (InterruptedException ie) {
1022: fail("Should not have been interrupted");
1023: }
1024: try {
1025: thread.join();
1026: } catch (InterruptedException ie) {
1027: fail("Should not have been interrupted");
1028: }
1029: testRoot.destroy();
1030: assertTrue(
1031: "Any thread should notify its ThreadGroup about its own death, even if killed:"
1032: + testRoot, passed[TEST_KILLING]);
1033:
1034: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1035: // - - - - - - -
1036: testRoot = new ThreadGroup(originalCurrent,
1037: "Test Forcing a throw of ThreadDeath") {
1038: @Override
1039: public void uncaughtException(Thread t, Throwable e) {
1040: if (e instanceof ThreadDeath) {
1041: passed[TEST_FORCING_THROW_THREAD_DEATH] = true;
1042: }
1043: // always forward, any exception
1044: super .uncaughtException(t, e);
1045: }
1046: };
1047:
1048: // Test if a Thread tells its ThreadGroup about ThreadDeath
1049: thread = new Thread(testRoot, null, "suicidal thread") {
1050: @Override
1051: public void run() {
1052: throw new ThreadDeath();
1053: }
1054: };
1055: thread.start();
1056: try {
1057: thread.join();
1058: } catch (InterruptedException ie) {
1059: fail("Should not have been interrupted");
1060: }
1061: testRoot.destroy();
1062: assertTrue(
1063: "Any thread should notify its ThreadGroup about its own death, even if suicide:"
1064: + testRoot,
1065: passed[TEST_FORCING_THROW_THREAD_DEATH]);
1066:
1067: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1068: // - - - - - - -
1069:
1070: testRoot = new ThreadGroup(originalCurrent, "Test ThreadDeath") {
1071: @Override
1072: public void uncaughtException(Thread t, Throwable e) {
1073: passed[TEST_DEATH] = false;
1074: // always forward, any exception
1075: super .uncaughtException(t, e);
1076: }
1077: };
1078:
1079: // Test if a Thread tells its ThreadGroup about ThreadDeath
1080: passed[TEST_DEATH] = true;
1081: thread = new Thread(testRoot, null, "no-op thread");
1082: thread.start();
1083: try {
1084: thread.join();
1085: } catch (InterruptedException ie) {
1086: fail("Should not have been interrupted");
1087: }
1088: testRoot.destroy();
1089: assertTrue(
1090: "A thread should not call uncaughtException when it dies:"
1091: + testRoot, passed[TEST_DEATH]);
1092:
1093: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1094: // - - - - - - -
1095:
1096: testRoot = new ThreadGroup(originalCurrent,
1097: "Test other Exception") {
1098: @Override
1099: public void uncaughtException(Thread t, Throwable e) {
1100: if (e instanceof TestException) {
1101: passed[TEST_OTHER] = true;
1102: } else {
1103: // only forward exceptions other than our test
1104: super .uncaughtException(t, e);
1105: }
1106: }
1107: };
1108:
1109: // Test if a Thread tells its ThreadGroup about an Exception
1110: thread = new Thread(testRoot, null, "no-op thread") {
1111: @Override
1112: public void run() {
1113: throw new TestException();
1114: }
1115: };
1116: thread.start();
1117: try {
1118: thread.join();
1119: } catch (InterruptedException ie) {
1120: fail("Should not have been interrupted");
1121: }
1122: testRoot.destroy();
1123: assertTrue(
1124: "Any thread should notify its ThreadGroup about an uncaught exception:"
1125: + testRoot, passed[TEST_OTHER]);
1126:
1127: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1128: // - - - - - - -
1129:
1130: // Our own uncaught exception class
1131: class UncaughtException extends TestException {
1132: private static final long serialVersionUID = 1L;
1133: }
1134:
1135: testRoot = new ThreadGroup(originalCurrent,
1136: "Test Exception in uncaught exception") {
1137: @Override
1138: public void uncaughtException(Thread t, Throwable e) {
1139: if (e instanceof TestException) {
1140: passed[TEST_EXCEPTION_IN_UNCAUGHT] = true;
1141: // Let's simulate an error inside our uncaughtException
1142: // method.
1143: // This should be no-op according to the spec
1144: throw new UncaughtException();
1145: }
1146: // only forward exceptions other than our test
1147: super .uncaughtException(t, e);
1148: }
1149: };
1150:
1151: // Test if an Exception in uncaughtException is really a no-op
1152: thread = new Thread(testRoot, null, "no-op thread") {
1153: @Override
1154: public void run() {
1155: try {
1156: throw new TestException();
1157: } catch (UncaughtException ue) {
1158: // any exception in my ThreadGroup's uncaughtException must
1159: // not be propagated.
1160: // If it gets propagated and we detected that, the test failed
1161: passed[TEST_EXCEPTION_IN_UNCAUGHT] = false;
1162: }
1163: }
1164: };
1165: thread.start();
1166: try {
1167: thread.join();
1168: } catch (InterruptedException ie) {
1169: fail("Should not have been interrupted");
1170: }
1171: testRoot.destroy();
1172: assertTrue(
1173: "Any uncaughtException in uncaughtException should be no-op:"
1174: + testRoot, passed[TEST_EXCEPTION_IN_UNCAUGHT]);
1175:
1176: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1177: // - - - - - - -
1178:
1179: // This is a mix of 2 of the tests above. It is assumed that ThreadDeath
1180: // and any random exception do work , tested separately. Now we test
1181: // if after an uncaughtException is forwarded to the ThreadGroup and
1182: // the Thread dies, if ThreadDeath is also forwarded. It should be
1183: // (so that a ThreadGroup can know its Thread died)
1184: testRoot = new ThreadGroup(originalCurrent,
1185: "Test Uncaught followed by ThreadDeath") {
1186: @Override
1187: public void uncaughtException(Thread t, Throwable e) {
1188: if (e instanceof ThreadDeath) {
1189: passed[TEST_DEATH_AFTER_UNCAUGHT] = true;
1190: }
1191: if (e instanceof TestException) {
1192: passed[TEST_OTHER_THEN_DEATH] = true;
1193: } else {
1194: // only forward exceptions other than our test
1195: super .uncaughtException(t, e);
1196: }
1197: }
1198: };
1199:
1200: // Test if a Thread tells its ThreadGroup about an Exception and also
1201: // ThreadDeath
1202: thread = new Thread(testRoot, null, "no-op thread") {
1203: @Override
1204: public void run() {
1205: throw new TestException();
1206: }
1207: };
1208: thread.start();
1209: try {
1210: thread.join();
1211: } catch (InterruptedException ie) {
1212: fail("Should not have been interrupted");
1213: }
1214: testRoot.destroy();
1215: }
1216:
1217: @Override
1218: protected void setUp() {
1219: initialThreadGroup = Thread.currentThread().getThreadGroup();
1220: rootThreadGroup = initialThreadGroup;
1221: while (rootThreadGroup.getParent() != null) {
1222: rootThreadGroup = rootThreadGroup.getParent();
1223: }
1224: }
1225:
1226: @Override
1227: protected void tearDown() {
1228: try {
1229: // Give the threads a chance to die.
1230: Thread.sleep(50);
1231: } catch (InterruptedException e) {
1232: }
1233: }
1234:
1235: private Thread[] threads(ThreadGroup parent) {
1236: // No API to get the count of immediate children only ?
1237: int count = parent.activeCount();
1238: Thread[] all = new Thread[count];
1239: int actualSize = parent.enumerate(all, false);
1240: Thread[] result;
1241: if (actualSize == all.length) {
1242: result = all;
1243: } else {
1244: result = new Thread[actualSize];
1245: System.arraycopy(all, 0, result, 0, actualSize);
1246: }
1247:
1248: return result;
1249:
1250: }
1251:
1252: private ThreadGroup getInitialThreadGroup() {
1253: return initialThreadGroup;
1254: }
1255:
1256: private ThreadGroup[] allGroups(ThreadGroup parent) {
1257: int count = parent.activeGroupCount();
1258: ThreadGroup[] all = new ThreadGroup[count];
1259: parent.enumerate(all, true);
1260: return all;
1261: }
1262:
1263: private void daemonTests() {
1264: // Test for method void java.lang.ThreadGroup.setDaemon(boolean)
1265:
1266: final ThreadGroup originalCurrent = getInitialThreadGroup();
1267: final ThreadGroup testRoot = new ThreadGroup(originalCurrent,
1268: "Test group");
1269:
1270: testRoot.setDaemon(true);
1271: assertTrue("Setting daemon&getting does not work", testRoot
1272: .isDaemon());
1273:
1274: testRoot.setDaemon(false);
1275: assertTrue("Setting daemon&getting does not work", !testRoot
1276: .isDaemon());
1277:
1278: testRoot.destroy();
1279:
1280: }
1281:
1282: private boolean wipeAllThreads(final ThreadGroup aGroup) {
1283: boolean ok = true;
1284: Thread[] threads = threads(aGroup);
1285: for (Thread t : threads) {
1286: ok = ok && wipeThread(t);
1287: }
1288:
1289: // Recursively for subgroups (if any)
1290: ThreadGroup[] children = groups(aGroup);
1291: for (ThreadGroup element : children) {
1292: ok = ok && wipeAllThreads(element);
1293: }
1294:
1295: return ok;
1296:
1297: }
1298:
1299: private boolean wipeSideEffectThreads(ThreadGroup aGroup) {
1300: boolean ok = true;
1301: Thread[] threads = threads(aGroup);
1302: for (Thread t : threads) {
1303: if (t.getName().equals("SimpleThread")
1304: || t.getName().equals("Bogus Name")
1305: || t.getName().equals("Testing")
1306: || t.getName().equals("foo")
1307: || t.getName().equals("Test Group")
1308: || t.getName().equals("Squawk")
1309: || t.getName().equals("Thread-1")
1310: || t.getName().equals("firstOne")
1311: || t.getName().equals("secondOne")
1312: || t.getName().equals("Thread-16")
1313: || t.getName().equals("Thread-14")) {
1314: ok = ok && wipeThread(t);
1315: }
1316: }
1317:
1318: // Recursively for subgroups (if any)
1319: ThreadGroup[] children = groups(aGroup);
1320:
1321: for (ThreadGroup element : children) {
1322: ok = ok && wipeSideEffectThreads(element);
1323: if (element.getName().equals("Test Group")
1324: || element.getName().equals("foo")
1325: || element.getName().equals("jp")) {
1326: element.destroy();
1327: }
1328: }
1329: try {
1330: // Give the threads a chance to die.
1331: Thread.sleep(50);
1332: } catch (InterruptedException e) {
1333: }
1334: return ok;
1335: }
1336:
1337: private void asyncBuildRandomTreeUnder(final ThreadGroup aGroup,
1338: final int depth, final Vector<ThreadGroup> allCreated) {
1339: if (depth <= 0) {
1340: return;
1341: }
1342:
1343: final int maxImmediateSubgroups = random(3);
1344: for (int i = 0; i < maxImmediateSubgroups; i++) {
1345: final int iClone = i;
1346: final String name = " Depth = " + depth + ",N = " + iClone
1347: + ",Vector size at creation: " + allCreated.size();
1348: // Use concurrency to maximize chance of exposing concurrency bugs
1349: // in ThreadGroups
1350: Thread t = new Thread(aGroup, name) {
1351: @Override
1352: public void run() {
1353: ThreadGroup newGroup = new ThreadGroup(aGroup, name);
1354: allCreated.addElement(newGroup);
1355: asyncBuildRandomTreeUnder(newGroup, depth - 1,
1356: allCreated);
1357: }
1358: };
1359: t.start();
1360: }
1361:
1362: }
1363:
1364: private Vector<ThreadGroup> asyncBuildRandomTreeUnder(
1365: final ThreadGroup aGroup, final int depth) {
1366: Vector<ThreadGroup> result = new Vector<ThreadGroup>();
1367: asyncBuildRandomTreeUnder(aGroup, depth, result);
1368: return result;
1369:
1370: }
1371:
1372: private boolean allSuspended(Vector<MyThread> threads) {
1373: for (int i = 0; i < threads.size(); i++) {
1374: MyThread t = threads.elementAt(i);
1375: if (t.isActivelyRunning()) {
1376: return false;
1377: }
1378: }
1379:
1380: return true;
1381:
1382: }
1383:
1384: private ThreadGroup[] groups(ThreadGroup parent) {
1385: // No API to get the count of immediate children only ?
1386: int count = parent.activeGroupCount();
1387: ThreadGroup[] all = new ThreadGroup[count];
1388: parent.enumerate(all, false);
1389: // Now we may have nulls in the array, we must find the actual size
1390: int actualSize = 0;
1391: for (; actualSize < all.length; actualSize++) {
1392: if (all[actualSize] == null) {
1393: break;
1394: }
1395: }
1396: ThreadGroup[] result;
1397: if (actualSize == all.length) {
1398: result = all;
1399: } else {
1400: result = new ThreadGroup[actualSize];
1401: System.arraycopy(all, 0, result, 0, actualSize);
1402: }
1403:
1404: return result;
1405:
1406: }
1407:
1408: private Vector<MyThread> populateGroupsWithThreads(
1409: final ThreadGroup aGroup, final int threadCount) {
1410: Vector<MyThread> result = new Vector<MyThread>();
1411: populateGroupsWithThreads(aGroup, threadCount, result);
1412: return result;
1413:
1414: }
1415:
1416: private void populateGroupsWithThreads(final ThreadGroup aGroup,
1417: final int threadCount, final Vector<MyThread> allCreated) {
1418: for (int i = 0; i < threadCount; i++) {
1419: final int iClone = i;
1420: final String name = "(MyThread)N =" + iClone + "/"
1421: + threadCount + " ,Vector size at creation: "
1422: + allCreated.size();
1423:
1424: MyThread t = new MyThread(aGroup, name);
1425: allCreated.addElement(t);
1426: }
1427:
1428: // Recursively for subgroups (if any)
1429: ThreadGroup[] children = groups(aGroup);
1430: for (ThreadGroup element : children) {
1431: populateGroupsWithThreads(element, threadCount, allCreated);
1432: }
1433:
1434: }
1435:
1436: private int random(int max) {
1437:
1438: return 1 + ((new Object()).hashCode() % max);
1439:
1440: }
1441:
1442: @SuppressWarnings("deprecation")
1443: private boolean wipeThread(Thread t) {
1444: t.stop();
1445: try {
1446: t.join(1000);
1447: } catch (InterruptedException ie) {
1448: fail("Should not have been interrupted");
1449: }
1450: // The thread had plenty (subjective) of time to die so there
1451: // is a problem.
1452: if (t.isAlive()) {
1453: return false;
1454: }
1455:
1456: return true;
1457: }
1458:
1459: private Vector<ThreadGroup> buildRandomTreeUnder(
1460: ThreadGroup aGroup, int depth) {
1461: Vector<ThreadGroup> result = asyncBuildRandomTreeUnder(aGroup,
1462: depth);
1463: while (true) {
1464: int sizeBefore = result.size();
1465: try {
1466: Thread.sleep(1000);
1467: int sizeAfter = result.size();
1468: // If no activity for a while, we assume async building may be
1469: // done.
1470: if (sizeBefore == sizeAfter) {
1471: // It can only be done if no more threads. Unfortunately we
1472: // are relying on this API to work as well.
1473: // If it does not, we may loop forever.
1474: if (aGroup.activeCount() == 0) {
1475: break;
1476: }
1477: }
1478: } catch (InterruptedException e) {
1479: }
1480: }
1481: return result;
1482:
1483: }
1484:
1485: private boolean arrayIncludes(Object[] array, Object toTest) {
1486: for (Object element : array) {
1487: if (element == toTest) {
1488: return true;
1489: }
1490: }
1491:
1492: return false;
1493: }
1494:
1495: protected void myassertTrue(String msg, boolean b) {
1496: // This method is defined here just to solve a visibility problem
1497: // of protected methods with inner types
1498: assertTrue(msg, b);
1499: }
1500:
1501: private ThreadGroup getRootThreadGroup() {
1502: return rootThreadGroup;
1503:
1504: }
1505: }
|