| /* |
| * 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); |
| } |
| } |
| } |