OldThreadGroupTest.java revision ab56f644a3d1a42658d4ec34650f7b882e29e374
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 // No-op in Android. Must neither have an effect nor throw an exception. 287 Thread.State state = thread.getState(); 288 group.resume(); 289 assertEquals(state, thread.getState()); 290 } 291 292 private Thread launchFiveSecondDummyThread(ThreadGroup group) { 293 Thread thread = new Thread(group, "Bar") { 294 public void run() { 295 try { 296 Thread.sleep(5000); 297 } catch (InterruptedException e) { 298 // Ignore 299 } 300 } 301 }; 302 303 thread.start(); 304 305 return thread; 306 } 307 308 /* 309 * @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable) 310 */ 311 public void uncaughtException(Thread t, Throwable e) { 312 interrupted = true; 313 Thread.setDefaultUncaughtExceptionHandler(null); 314 } 315 316 @Override 317 protected void setUp() { 318 initialThreadGroup = Thread.currentThread().getThreadGroup(); 319 ThreadGroup rootThreadGroup = initialThreadGroup; 320 while (rootThreadGroup.getParent() != null) { 321 rootThreadGroup = rootThreadGroup.getParent(); 322 } 323 } 324 325 @Override 326 protected void tearDown() { 327 try { 328 // Give the threads a chance to die. 329 Thread.sleep(50); 330 } catch (InterruptedException e) { 331 } 332 } 333 334 private ThreadGroup getInitialThreadGroup() { 335 return initialThreadGroup; 336 } 337 338 private ThreadGroup[] groups(ThreadGroup parent) { 339 // No API to get the count of immediate children only 340 int count = parent.activeGroupCount(); 341 ThreadGroup[] all = new ThreadGroup[count]; 342 parent.enumerate(all, false); 343 // Now we may have nulls in the array, we must find the actual size 344 int actualSize = 0; 345 for (; actualSize < all.length; actualSize++) { 346 if (all[actualSize] == null) { 347 break; 348 } 349 } 350 return Arrays.copyOfRange(all, 0, actualSize); 351 } 352 353 private List<MyThread> populateGroupsWithThreads(ThreadGroup group, int threadCount) { 354 List<MyThread> result = new ArrayList<MyThread>(); 355 populateGroupsWithThreads(group, threadCount, result); 356 return result; 357 } 358 359 private void populateGroupsWithThreads(ThreadGroup group, int threadCount, List<MyThread> out) { 360 for (int i = 0; i < threadCount; i++) { 361 out.add(new MyThread(group, "MyThread " + i + " of " + threadCount)); 362 } 363 364 // Recursively for subgroups (if any) 365 ThreadGroup[] children = groups(group); 366 for (ThreadGroup element : children) { 367 populateGroupsWithThreads(element, threadCount, out); 368 } 369 } 370} 371