OldThreadGroupTest.java revision 405d740fa49c15eaf07e6eeb5844a90a256f78ef
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 libcore.java.lang; 19 20import java.util.ArrayList; 21import java.util.Arrays; 22import java.util.HashSet; 23import java.util.List; 24import java.util.Set; 25import junit.framework.TestCase; 26 27public class OldThreadGroupTest extends TestCase implements Thread.UncaughtExceptionHandler { 28 29 class MyThread extends Thread { 30 public volatile int heartBeat = 0; 31 32 public MyThread(ThreadGroup group, String name) 33 throws SecurityException, IllegalThreadStateException { 34 super(group, name); 35 } 36 37 @Override 38 public void run() { 39 while (true) { 40 heartBeat++; 41 try { 42 Thread.sleep(50); 43 } catch (InterruptedException e) { 44 break; 45 } 46 } 47 } 48 49 public boolean isActivelyRunning() { 50 long MAX_WAIT = 100; 51 return isActivelyRunning(MAX_WAIT); 52 } 53 54 public boolean isActivelyRunning(long maxWait) { 55 int beat = heartBeat; 56 long start = System.currentTimeMillis(); 57 do { 58 Thread.yield(); 59 int beat2 = heartBeat; 60 if (beat != beat2) { 61 return true; 62 } 63 } while (System.currentTimeMillis() - start < maxWait); 64 return false; 65 } 66 67 } 68 69 private ThreadGroup initialThreadGroup = null; 70 71 public void test_activeGroupCount() { 72 ThreadGroup tg = new ThreadGroup("group count"); 73 assertEquals("Incorrect number of groups", 74 0, tg.activeGroupCount()); 75 Thread t1 = new Thread(tg, new Runnable() { 76 public void run() { 77 78 } 79 }); 80 assertEquals("Incorrect number of groups", 81 0, tg.activeGroupCount()); 82 t1.start(); 83 assertEquals("Incorrect number of groups", 84 0, tg.activeGroupCount()); 85 new ThreadGroup(tg, "test group 1"); 86 assertEquals("Incorrect number of groups", 87 1, tg.activeGroupCount()); 88 new ThreadGroup(tg, "test group 2"); 89 assertEquals("Incorrect number of groups", 90 2, tg.activeGroupCount()); 91 } 92 93 @SuppressWarnings("deprecation") 94 public void test_allowThreadSuspensionZ() { 95 ThreadGroup tg = new ThreadGroup("thread suspension"); 96 assertTrue("Thread suspention can not be changed", 97 tg.allowThreadSuspension(false)); 98 assertTrue("Thread suspention can not be changed", 99 tg.allowThreadSuspension(true)); 100 } 101 102 /* 103 * Checks whether the current Thread is in the given list. 104 */ 105 private boolean inListOfThreads(Thread[] threads) { 106 for (int i = 0; i < threads.length; i++) { 107 if (Thread.currentThread() == threads[i]) { 108 return true; 109 } 110 } 111 112 return false; 113 } 114 115 public void test_enumerateLThreadArray() { 116 int numThreads = initialThreadGroup.activeCount(); 117 Thread[] listOfThreads = new Thread[numThreads]; 118 119 int countThread = initialThreadGroup.enumerate(listOfThreads); 120 assertEquals(numThreads, countThread); 121 assertTrue("Current thread must be in enumeration of threads", 122 inListOfThreads(listOfThreads)); 123 } 124 125 public void test_enumerateLThreadArrayLZtest_enumerateLThreadArrayLZ() throws Exception { 126 // capture the initial condition 127 int initialThreadCount = initialThreadGroup.activeCount(); 128 Thread[] initialThreads = new Thread[initialThreadCount]; 129 assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, false)); 130 assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, true)); 131 assertTrue(inListOfThreads(initialThreads)); 132 133 // start some the threads and see how the count changes 134 ThreadGroup group = new ThreadGroup(initialThreadGroup, "enumerateThreadArray"); 135 int groupSize = 3; 136 List<MyThread> newThreads = populateGroupsWithThreads(group, groupSize); 137 assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, true)); 138 assertTrue(inListOfThreads(initialThreads)); 139 for(MyThread thread : newThreads) { 140 thread.start(); 141 } 142 Thread.sleep(500); // starting threads isn't instant! 143 int afterStartCount = initialThreadGroup.activeCount(); 144 Set<Thread> initialPlusNew = new HashSet<Thread>(); 145 initialPlusNew.addAll(Arrays.asList(initialThreads)); 146 initialPlusNew.addAll(newThreads); 147 Thread[] afterStartThreads = new Thread[afterStartCount]; 148 assertEquals(afterStartCount, initialThreadGroup.enumerate(afterStartThreads, true)); 149 assertEquals(initialPlusNew, new HashSet<Thread>(Arrays.asList(afterStartThreads))); 150 assertTrue(inListOfThreads(afterStartThreads)); 151 152 // kill the threads and count 'em again 153 for(MyThread thread : newThreads) { 154 thread.interrupt(); 155 } 156 Thread.sleep(500); // killing threads isn't instant 157 int afterDeathCount = initialThreadGroup.activeCount(); 158 Thread[] afterDeathThreads = new Thread[afterDeathCount]; 159 assertEquals(afterDeathCount, initialThreadGroup.enumerate(afterDeathThreads, false)); 160 assertEquals(Arrays.asList(initialThreads), Arrays.asList(afterDeathThreads)); 161 assertTrue(inListOfThreads(afterDeathThreads)); 162 } 163 164 public void test_enumerateLThreadGroupArray() { 165 int numGroupThreads = initialThreadGroup.activeGroupCount(); 166 ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads]; 167 168 int countGroupThread = initialThreadGroup.enumerate(listOfGroups); 169 assertEquals(numGroupThreads, countGroupThread); 170 171 ThreadGroup[] listOfGroups1 = new ThreadGroup[numGroupThreads + 1]; 172 countGroupThread = initialThreadGroup.enumerate(listOfGroups1); 173 assertEquals(numGroupThreads, countGroupThread); 174 assertNull(listOfGroups1[listOfGroups1.length - 1]); 175 176 ThreadGroup[] listOfGroups2 = new ThreadGroup[numGroupThreads - 1]; 177 countGroupThread = initialThreadGroup.enumerate(listOfGroups2); 178 assertEquals(numGroupThreads - 1, countGroupThread); 179 180 ThreadGroup thrGroup1 = new ThreadGroup("Test Group 1"); 181 countGroupThread = thrGroup1.enumerate(listOfGroups); 182 assertEquals(0, countGroupThread); 183 } 184 185 public void test_enumerateLThreadGroupArrayLZ() { 186 ThreadGroup thrGroup = new ThreadGroup("Test Group 1"); 187 List<MyThread> subThreads = populateGroupsWithThreads(thrGroup, 3); 188 int numGroupThreads = thrGroup.activeGroupCount(); 189 ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads]; 190 191 assertEquals(0, thrGroup.enumerate(listOfGroups, true)); 192 assertEquals(0, thrGroup.enumerate(listOfGroups, false)); 193 194 for(MyThread thr:subThreads) { 195 thr.start(); 196 } 197 198 numGroupThreads = thrGroup.activeGroupCount(); 199 listOfGroups = new ThreadGroup[numGroupThreads]; 200 201 assertEquals(0, thrGroup.enumerate(listOfGroups, true)); 202 assertEquals(0, thrGroup.enumerate(listOfGroups, false)); 203 204 ThreadGroup subGroup1 = new ThreadGroup(thrGroup, "Test Group 2"); 205 List<MyThread> subThreads1 = populateGroupsWithThreads(subGroup1, 3); 206 numGroupThreads = thrGroup.activeGroupCount(); 207 listOfGroups = new ThreadGroup[numGroupThreads]; 208 209 assertEquals(1, thrGroup.enumerate(listOfGroups, true)); 210 assertEquals(1, thrGroup.enumerate(listOfGroups, false)); 211 212 for(MyThread thr:subThreads1) { 213 thr.start(); 214 } 215 numGroupThreads = thrGroup.activeGroupCount(); 216 listOfGroups = new ThreadGroup[numGroupThreads]; 217 218 assertEquals(1, thrGroup.enumerate(listOfGroups, true)); 219 assertEquals(1, thrGroup.enumerate(listOfGroups, false)); 220 221 for(MyThread thr:subThreads) { 222 thr.interrupt(); 223 } 224 225 ThreadGroup subGroup2 = new ThreadGroup(subGroup1, "Test Group 3"); 226 List<MyThread> subThreads2 = populateGroupsWithThreads(subGroup2, 3); 227 numGroupThreads = thrGroup.activeGroupCount(); 228 listOfGroups = new ThreadGroup[numGroupThreads]; 229 230 assertEquals(2, thrGroup.enumerate(listOfGroups, true)); 231 assertEquals(1, thrGroup.enumerate(listOfGroups, false)); 232 } 233 234 /** 235 * @tests java.lang.ThreadGroup#interrupt() 236 */ 237 private static boolean interrupted = false; 238 public void test_interrupt() { 239 240 Thread.setDefaultUncaughtExceptionHandler(this); 241 ThreadGroup tg = new ThreadGroup("interrupt"); 242 Thread t1 = new Thread(tg, new Runnable() { 243 public void run() { 244 try { 245 Thread.sleep(5000); 246 } catch (InterruptedException e) { 247 fail("ok"); 248 } 249 } 250 }); 251 assertFalse("Incorrect state of thread", interrupted); 252 t1.start(); 253 assertFalse("Incorrect state of thread", interrupted); 254 t1.interrupt(); 255 try { 256 t1.join(); 257 } catch (InterruptedException e) { 258 } 259 assertTrue("Incorrect state of thread", interrupted); 260 tg.destroy(); 261 } 262 263 public void test_isDestroyed() { 264 final ThreadGroup originalCurrent = getInitialThreadGroup(); 265 final ThreadGroup testRoot = new ThreadGroup(originalCurrent, 266 "Test group"); 267 assertFalse("Test group is not destroyed yet", 268 testRoot.isDestroyed()); 269 testRoot.destroy(); 270 assertTrue("Test group already destroyed", 271 testRoot.isDestroyed()); 272 } 273 274 @SuppressWarnings("deprecation") 275 public void test_resume() { 276 ThreadGroup group = new ThreadGroup("Foo"); 277 278 Thread thread = launchFiveSecondDummyThread(group); 279 280 try { 281 Thread.sleep(1000); 282 } catch (InterruptedException e) { 283 // Ignore 284 } 285 286 try { 287 group.resume(); 288 fail(); 289 } catch (UnsupportedOperationException expected) { 290 } 291 } 292 293 private Thread launchFiveSecondDummyThread(ThreadGroup group) { 294 Thread thread = new Thread(group, "Bar") { 295 public void run() { 296 try { 297 Thread.sleep(5000); 298 } catch (InterruptedException e) { 299 // Ignore 300 } 301 } 302 }; 303 304 thread.start(); 305 306 return thread; 307 } 308 309 /* 310 * @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable) 311 */ 312 public void uncaughtException(Thread t, Throwable e) { 313 interrupted = true; 314 Thread.setDefaultUncaughtExceptionHandler(null); 315 } 316 317 @Override 318 protected void setUp() { 319 initialThreadGroup = Thread.currentThread().getThreadGroup(); 320 ThreadGroup rootThreadGroup = initialThreadGroup; 321 while (rootThreadGroup.getParent() != null) { 322 rootThreadGroup = rootThreadGroup.getParent(); 323 } 324 } 325 326 @Override 327 protected void tearDown() { 328 try { 329 // Give the threads a chance to die. 330 Thread.sleep(50); 331 } catch (InterruptedException e) { 332 } 333 } 334 335 private ThreadGroup getInitialThreadGroup() { 336 return initialThreadGroup; 337 } 338 339 private ThreadGroup[] groups(ThreadGroup parent) { 340 // No API to get the count of immediate children only 341 int count = parent.activeGroupCount(); 342 ThreadGroup[] all = new ThreadGroup[count]; 343 parent.enumerate(all, false); 344 // Now we may have nulls in the array, we must find the actual size 345 int actualSize = 0; 346 for (; actualSize < all.length; actualSize++) { 347 if (all[actualSize] == null) { 348 break; 349 } 350 } 351 return Arrays.copyOfRange(all, 0, actualSize); 352 } 353 354 private List<MyThread> populateGroupsWithThreads(ThreadGroup group, int threadCount) { 355 List<MyThread> result = new ArrayList<MyThread>(); 356 populateGroupsWithThreads(group, threadCount, result); 357 return result; 358 } 359 360 private void populateGroupsWithThreads(ThreadGroup group, int threadCount, List<MyThread> out) { 361 for (int i = 0; i < threadCount; i++) { 362 out.add(new MyThread(group, "MyThread " + i + " of " + threadCount)); 363 } 364 365 // Recursively for subgroups (if any) 366 ThreadGroup[] children = groups(group); 367 for (ThreadGroup element : children) { 368 populateGroupsWithThreads(element, threadCount, out); 369 } 370 } 371} 372