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