1be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson/*
2be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * Copyright (C) 2010 The Android Open Source Project
3be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson *
4be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * you may not use this file except in compliance with the License.
6be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * You may obtain a copy of the License at
7be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson *
8be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson *
10be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * See the License for the specific language governing permissions and
14be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson * limitations under the License.
15be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson */
16be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson
17be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilsonpackage libcore.java.lang;
18be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson
19be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilsonimport java.util.concurrent.atomic.AtomicInteger;
200647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilsonimport junit.framework.Assert;
21be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilsonimport junit.framework.TestCase;
221a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilsonimport libcore.java.lang.ref.FinalizationTester;
23be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson
24be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilsonpublic final class ThreadTest extends TestCase {
25be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson
260647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    /**
270647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson     * getContextClassLoader returned a non-application class loader.
280647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson     * http://code.google.com/p/android/issues/detail?id=5697
290647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson     */
300647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    public void testJavaContextClassLoader() throws Exception {
310647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        Assert.assertNotNull("Must have a Java context ClassLoader",
320647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                Thread.currentThread().getContextClassLoader());
330647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    }
340647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson
35be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson    public void testLeakingStartedThreads() {
36be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        final AtomicInteger finalizedThreadsCount = new AtomicInteger();
37be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        for (int i = 0; true; i++) {
38be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson            try {
39be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson                newThread(finalizedThreadsCount, 1024 << i).start();
40be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson            } catch (OutOfMemoryError expected) {
41be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson                break;
42be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson            }
43be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        }
441a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson        FinalizationTester.induceFinalization();
45be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        assertTrue("Started threads were never finalized!", finalizedThreadsCount.get() > 0);
46be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson    }
47be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson
48be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson    public void testLeakingUnstartedThreads() {
49be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        final AtomicInteger finalizedThreadsCount = new AtomicInteger();
50be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        for (int i = 0; true; i++) {
51be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson            try {
52be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson                newThread(finalizedThreadsCount, 1024 << i);
53be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson            } catch (OutOfMemoryError expected) {
54be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson                break;
55be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson            }
56be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        }
571a9cff8f68deffd618c5cba1f22f0fb0e396e067Jesse Wilson        FinalizationTester.induceFinalization();
58be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson        assertTrue("Unstarted threads were never finalized!", finalizedThreadsCount.get() > 0);
59be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson    }
60be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson
61b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    public void testThreadSleep() throws Exception {
62b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        int millis = 1000;
63b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        long start = System.currentTimeMillis();
64b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
65b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        Thread.sleep(millis);
66b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
67b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        long elapsed = System.currentTimeMillis() - start;
68b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        long offBy = Math.abs(elapsed - millis);
69b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
70b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        assertTrue("Actual sleep off by " + offBy + " ms", offBy <= 250);
71b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom    }
72b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom
73b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom    public void testThreadInterrupted() throws Exception {
74b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        Thread.currentThread().interrupt();
75b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        try {
76b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            Thread.sleep(0);
77b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            fail();
78b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        } catch (InterruptedException e) {
79b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            assertFalse(Thread.currentThread().isInterrupted());
80b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        }
81b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom    }
82b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom
83b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom    public void testThreadSleepIllegalArguments() throws Exception {
84b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom
85b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        try {
86b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            Thread.sleep(-1);
87b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            fail();
88b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        } catch (IllegalArgumentException expected) {
89b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        }
90b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom
91b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        try {
92b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            Thread.sleep(0, -1);
93b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            fail();
94b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        } catch (IllegalArgumentException expected) {
95b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        }
96b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom
97b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        try {
98b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            Thread.sleep(0, 1000000);
99b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom            fail();
100b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        } catch (IllegalArgumentException expected) {
101b5a43a8ad530a60469bf9244a157079c93c07c8bBrian Carlstrom        }
102b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    }
103b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
104b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    public void testThreadWakeup() throws Exception {
105b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        WakeupTestThread t1 = new WakeupTestThread();
106b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        WakeupTestThread t2 = new WakeupTestThread();
107b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
108b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        t1.start();
109b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        t2.start();
110b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        assertTrue("Threads already finished", !t1.done && !t2.done);
111b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
112b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        t1.interrupt();
113b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        t2.interrupt();
114b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
115b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        Thread.sleep(1000);
116b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        assertTrue("Threads did not finish", t1.done && t2.done);
117b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    }
118b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
119b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    public void testContextClassLoaderIsNotNull() {
120b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        assertNotNull(Thread.currentThread().getContextClassLoader());
121b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    }
122b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
123b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    public void testContextClassLoaderIsInherited() {
124b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        Thread other = new Thread();
125b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        assertSame(Thread.currentThread().getContextClassLoader(), other.getContextClassLoader());
126be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson    }
1270647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson
1280647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    /**
1290647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson     * Thread.getStackTrace() is broken. http://b/1252043
1300647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson     */
1310647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    public void testGetStackTrace() throws Exception {
1320647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        Thread t1 = new Thread("t1") {
1330647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson            @Override public void run() {
1340647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                doSomething();
1350647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson            }
1360647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson            public void doSomething() {
1370647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                for (int i = 0; i < 20;) {
1380647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                    try {
1390647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                        Thread.sleep(100);
1400647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                    } catch (InterruptedException ignored) {
1410647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                    }
1420647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                }
1430647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson            }
1440647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        };
1450647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        t1.start();
1460647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        Thread.sleep(1000);
1470647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        StackTraceElement[] traces = t1.getStackTrace();
1480647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        StackTraceElement trace = traces[traces.length - 2];
1490647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson
1500647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        // Expect to find MyThread.doSomething in the trace
1510647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        assertTrue(trace.getClassName().contains("ThreadTest")
1520647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                && trace.getMethodName().equals("doSomething"));
1530647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    }
1540647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson
1550647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    public void testGetAllStackTracesIncludesAllGroups() throws Exception {
1560647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        final AtomicInteger visibleTraces = new AtomicInteger();
1570647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        ThreadGroup group = new ThreadGroup("1");
1580647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        Thread t2 = new Thread(group, "t2") {
1590647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson            @Override public void run() {
1600647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson                visibleTraces.set(Thread.getAllStackTraces().size());
1610647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson            }
1620647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        };
1630647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        t2.start();
1640647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        t2.join();
1650647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson
1660647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        // Expect to see the traces of all threads (not just t2)
1670647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson        assertTrue("Must have traces for all threads", visibleTraces.get() > 1);
1680647bfed6eda99ad77b2dfe8e3696e3fabfaf3ccJesse Wilson    }
169b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
170b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    private Thread newThread(final AtomicInteger finalizedThreadsCount, final int size) {
171b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        return new Thread() {
172b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            long[] memoryPressure = new long[size];
173b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            @Override protected void finalize() throws Throwable {
174b20185245f53374b3a86705ac152fd88e4bddec5jeffhao                super.finalize();
175b20185245f53374b3a86705ac152fd88e4bddec5jeffhao                finalizedThreadsCount.incrementAndGet();
176b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            }
177b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        };
178b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    }
179b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
180b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    private class WakeupTestThread extends Thread {
181b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        public boolean done;
182b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
183b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        public void run() {
184b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            done = false;
185b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
186b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            // Sleep for a while (1 min)
187b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            try {
188b20185245f53374b3a86705ac152fd88e4bddec5jeffhao                Thread.sleep(60000);
189c3d53e68cbf91fb4c16abb88f8bf8a8e4be4d706Jesse Wilson            } catch (InterruptedException ignored) {
190b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            }
191b20185245f53374b3a86705ac152fd88e4bddec5jeffhao
192b20185245f53374b3a86705ac152fd88e4bddec5jeffhao            done = true;
193b20185245f53374b3a86705ac152fd88e4bddec5jeffhao        }
194b20185245f53374b3a86705ac152fd88e4bddec5jeffhao    }
195be013ce620f6d3bd24f7f0b631a36f70197ac3e3Jesse Wilson}
196