/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package libcore.java.lang; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import junit.framework.TestCase; public class OldThreadGroupTest extends TestCase implements Thread.UncaughtExceptionHandler { class MyThread extends Thread { public volatile int heartBeat = 0; public MyThread(ThreadGroup group, String name) throws SecurityException, IllegalThreadStateException { super(group, name); } @Override public void run() { while (true) { heartBeat++; try { Thread.sleep(50); } catch (InterruptedException e) { break; } } } public boolean isActivelyRunning() { long MAX_WAIT = 100; return isActivelyRunning(MAX_WAIT); } public boolean isActivelyRunning(long maxWait) { int beat = heartBeat; long start = System.currentTimeMillis(); do { Thread.yield(); int beat2 = heartBeat; if (beat != beat2) { return true; } } while (System.currentTimeMillis() - start < maxWait); return false; } } private ThreadGroup initialThreadGroup = null; public void test_activeGroupCount() { ThreadGroup tg = new ThreadGroup("group count"); assertEquals("Incorrect number of groups", 0, tg.activeGroupCount()); Thread t1 = new Thread(tg, new Runnable() { public void run() { } }); assertEquals("Incorrect number of groups", 0, tg.activeGroupCount()); t1.start(); assertEquals("Incorrect number of groups", 0, tg.activeGroupCount()); new ThreadGroup(tg, "test group 1"); assertEquals("Incorrect number of groups", 1, tg.activeGroupCount()); new ThreadGroup(tg, "test group 2"); assertEquals("Incorrect number of groups", 2, tg.activeGroupCount()); } @SuppressWarnings("deprecation") public void test_allowThreadSuspensionZ() { ThreadGroup tg = new ThreadGroup("thread suspension"); assertTrue("Thread suspention can not be changed", tg.allowThreadSuspension(false)); assertTrue("Thread suspention can not be changed", tg.allowThreadSuspension(true)); } /* * Checks whether the current Thread is in the given list. */ private boolean inListOfThreads(Thread[] threads) { for (int i = 0; i < threads.length; i++) { if (Thread.currentThread() == threads[i]) { return true; } } return false; } public void test_enumerateLThreadArray() { int numThreads = initialThreadGroup.activeCount(); Thread[] listOfThreads = new Thread[numThreads]; int countThread = initialThreadGroup.enumerate(listOfThreads); assertEquals(numThreads, countThread); assertTrue("Current thread must be in enumeration of threads", inListOfThreads(listOfThreads)); } public void test_enumerateLThreadArrayLZtest_enumerateLThreadArrayLZ() throws Exception { // capture the initial condition int initialThreadCount = initialThreadGroup.activeCount(); Thread[] initialThreads = new Thread[initialThreadCount]; assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, false)); assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, true)); assertTrue(inListOfThreads(initialThreads)); // start some the threads and see how the count changes ThreadGroup group = new ThreadGroup(initialThreadGroup, "enumerateThreadArray"); int groupSize = 3; List<MyThread> newThreads = populateGroupsWithThreads(group, groupSize); assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, true)); assertTrue(inListOfThreads(initialThreads)); for(MyThread thread : newThreads) { thread.start(); } Thread.sleep(500); // starting threads isn't instant! int afterStartCount = initialThreadGroup.activeCount(); Set<Thread> initialPlusNew = new HashSet<Thread>(); initialPlusNew.addAll(Arrays.asList(initialThreads)); initialPlusNew.addAll(newThreads); Thread[] afterStartThreads = new Thread[afterStartCount]; assertEquals(afterStartCount, initialThreadGroup.enumerate(afterStartThreads, true)); assertEquals(initialPlusNew, new HashSet<Thread>(Arrays.asList(afterStartThreads))); assertTrue(inListOfThreads(afterStartThreads)); // kill the threads and count 'em again for(MyThread thread : newThreads) { thread.interrupt(); } Thread.sleep(500); // killing threads isn't instant int afterDeathCount = initialThreadGroup.activeCount(); Thread[] afterDeathThreads = new Thread[afterDeathCount]; assertEquals(afterDeathCount, initialThreadGroup.enumerate(afterDeathThreads, false)); assertEquals(Arrays.asList(initialThreads), Arrays.asList(afterDeathThreads)); assertTrue(inListOfThreads(afterDeathThreads)); } public void test_enumerateLThreadGroupArray() { int numChildGroupsBefore = initialThreadGroup.activeGroupCount(); ThreadGroup childGroup = new ThreadGroup(initialThreadGroup, "child group"); int numChildGroupsAfter = initialThreadGroup.activeGroupCount(); assertTrue(initialThreadGroup.toString(), numChildGroupsAfter == numChildGroupsBefore + 1); ThreadGroup[] listOfGroups = new ThreadGroup[numChildGroupsAfter]; int countGroupThread = initialThreadGroup.enumerate(listOfGroups); assertEquals(numChildGroupsAfter, countGroupThread); assertTrue(Arrays.asList(listOfGroups).contains(childGroup)); ThreadGroup[] listOfGroups1 = new ThreadGroup[numChildGroupsAfter + 1]; countGroupThread = initialThreadGroup.enumerate(listOfGroups1); assertEquals(numChildGroupsAfter, countGroupThread); assertNull(listOfGroups1[listOfGroups1.length - 1]); ThreadGroup[] listOfGroups2 = new ThreadGroup[numChildGroupsAfter - 1]; countGroupThread = initialThreadGroup.enumerate(listOfGroups2); assertEquals(numChildGroupsAfter - 1, countGroupThread); ThreadGroup thrGroup1 = new ThreadGroup("Test Group 1"); countGroupThread = thrGroup1.enumerate(listOfGroups); assertEquals(0, countGroupThread); childGroup.destroy(); assertTrue(initialThreadGroup.activeGroupCount() == numChildGroupsBefore + 1); } public void test_enumerateLThreadGroupArrayLZ() { ThreadGroup thrGroup = new ThreadGroup("Test Group 1"); List<MyThread> subThreads = populateGroupsWithThreads(thrGroup, 3); int numGroupThreads = thrGroup.activeGroupCount(); ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads]; assertEquals(0, thrGroup.enumerate(listOfGroups, true)); assertEquals(0, thrGroup.enumerate(listOfGroups, false)); for(MyThread thr:subThreads) { thr.start(); } numGroupThreads = thrGroup.activeGroupCount(); listOfGroups = new ThreadGroup[numGroupThreads]; assertEquals(0, thrGroup.enumerate(listOfGroups, true)); assertEquals(0, thrGroup.enumerate(listOfGroups, false)); ThreadGroup subGroup1 = new ThreadGroup(thrGroup, "Test Group 2"); List<MyThread> subThreads1 = populateGroupsWithThreads(subGroup1, 3); numGroupThreads = thrGroup.activeGroupCount(); listOfGroups = new ThreadGroup[numGroupThreads]; assertEquals(1, thrGroup.enumerate(listOfGroups, true)); assertEquals(1, thrGroup.enumerate(listOfGroups, false)); for(MyThread thr:subThreads1) { thr.start(); } numGroupThreads = thrGroup.activeGroupCount(); listOfGroups = new ThreadGroup[numGroupThreads]; assertEquals(1, thrGroup.enumerate(listOfGroups, true)); assertEquals(1, thrGroup.enumerate(listOfGroups, false)); for(MyThread thr:subThreads) { thr.interrupt(); } ThreadGroup subGroup2 = new ThreadGroup(subGroup1, "Test Group 3"); List<MyThread> subThreads2 = populateGroupsWithThreads(subGroup2, 3); numGroupThreads = thrGroup.activeGroupCount(); listOfGroups = new ThreadGroup[numGroupThreads]; assertEquals(2, thrGroup.enumerate(listOfGroups, true)); assertEquals(1, thrGroup.enumerate(listOfGroups, false)); } /** * java.lang.ThreadGroup#interrupt() */ private static boolean interrupted = false; public void test_interrupt() { Thread.setDefaultUncaughtExceptionHandler(this); ThreadGroup tg = new ThreadGroup("interrupt"); Thread t1 = new Thread(tg, new Runnable() { public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { fail("ok"); } } }); assertFalse("Incorrect state of thread", interrupted); t1.start(); assertFalse("Incorrect state of thread", interrupted); t1.interrupt(); try { t1.join(); } catch (InterruptedException e) { } assertTrue("Incorrect state of thread", interrupted); tg.destroy(); } public void test_isDestroyed() { final ThreadGroup originalCurrent = getInitialThreadGroup(); final ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group"); assertFalse("Test group is not destroyed yet", testRoot.isDestroyed()); testRoot.destroy(); assertTrue("Test group already destroyed", testRoot.isDestroyed()); } @SuppressWarnings("deprecation") public void test_resume() { ThreadGroup group = new ThreadGroup("Foo"); Thread thread = launchFiveSecondDummyThread(group); try { Thread.sleep(1000); } catch (InterruptedException e) { // Ignore } try { group.resume(); fail(); } catch (UnsupportedOperationException expected) { } } private Thread launchFiveSecondDummyThread(ThreadGroup group) { Thread thread = new Thread(group, "Bar") { public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { // Ignore } } }; thread.start(); return thread; } /* * @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable) */ public void uncaughtException(Thread t, Throwable e) { interrupted = true; Thread.setDefaultUncaughtExceptionHandler(null); } @Override protected void setUp() { initialThreadGroup = Thread.currentThread().getThreadGroup(); ThreadGroup rootThreadGroup = initialThreadGroup; while (rootThreadGroup.getParent() != null) { rootThreadGroup = rootThreadGroup.getParent(); } } @Override protected void tearDown() { try { // Give the threads a chance to die. Thread.sleep(50); } catch (InterruptedException e) { } } private ThreadGroup getInitialThreadGroup() { return initialThreadGroup; } private ThreadGroup[] groups(ThreadGroup parent) { // No API to get the count of immediate children only int count = parent.activeGroupCount(); ThreadGroup[] all = new ThreadGroup[count]; parent.enumerate(all, false); // Now we may have nulls in the array, we must find the actual size int actualSize = 0; for (; actualSize < all.length; actualSize++) { if (all[actualSize] == null) { break; } } return Arrays.copyOfRange(all, 0, actualSize); } private List<MyThread> populateGroupsWithThreads(ThreadGroup group, int threadCount) { List<MyThread> result = new ArrayList<MyThread>(); populateGroupsWithThreads(group, threadCount, result); return result; } private void populateGroupsWithThreads(ThreadGroup group, int threadCount, List<MyThread> out) { for (int i = 0; i < threadCount; i++) { out.add(new MyThread(group, "MyThread " + i + " of " + threadCount)); } // Recursively for subgroups (if any) ThreadGroup[] children = groups(group); for (ThreadGroup element : children) { populateGroupsWithThreads(element, threadCount, out); } } }