1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Iterator;
20 import java.util.List;
21 
22 /**
23  * Test some basic thread stuff.
24  */
25 public class Main {
main(String[] args)26     public static void main(String[] args) throws Exception {
27         System.loadLibrary(args[0]);
28         System.out.println("thread test starting");
29         testThreadCapacity();
30         testThreadDaemons();
31         testSleepZero();
32         testSetName();
33         testThreadPriorities();
34         testMainThreadGroup();
35         testMainThreadAllStackTraces();
36         System.out.println("thread test done");
37     }
38 
39     /*
40      * Simple thread capacity test.
41      */
testThreadCapacity()42     private static void testThreadCapacity() throws Exception {
43         TestCapacityThread[] threads = new TestCapacityThread[128];
44         for (int i = 0; i < threads.length; i++) {
45             threads[i] = new TestCapacityThread();
46         }
47 
48         for (TestCapacityThread thread : threads) {
49             thread.start();
50         }
51         for (TestCapacityThread thread : threads) {
52             thread.join();
53         }
54 
55         System.out.println("testThreadCapacity thread count: " + TestCapacityThread.mCount);
56     }
57 
58     private static class TestCapacityThread extends Thread {
59         static int mCount = 0;
run()60         public void run() {
61             synchronized (TestCapacityThread.class) {
62                 ++mCount;
63             }
64             try {
65                 sleep(1000);
66             } catch (Exception ex) {
67             }
68         }
69     }
70 
testThreadDaemons()71     private static void testThreadDaemons() {
72         Thread t = new Thread(null, new TestDaemonThread(), "TestDaemonThread", 7168);
73 
74         t.setDaemon(false);
75 
76         System.out.print("testThreadDaemons starting thread '" + t.getName() + "'\n");
77         t.start();
78 
79         try {
80             t.join();
81         } catch (InterruptedException ex) {
82             ex.printStackTrace(System.out);
83         }
84 
85         System.out.print("testThreadDaemons finished\n");
86     }
87 
88     private static class TestDaemonThread implements Runnable {
run()89         public void run() {
90             System.out.print("testThreadDaemons @ Thread running\n");
91 
92             try {
93                 Thread.currentThread().setDaemon(true);
94                 System.out.print("testThreadDaemons @ FAILED: setDaemon() succeeded\n");
95             } catch (IllegalThreadStateException itse) {
96                 System.out.print("testThreadDaemons @ Got expected setDaemon exception\n");
97             }
98 
99             try {
100                 Thread.sleep(2000);
101             }
102             catch (InterruptedException ie) {
103                 System.out.print("testThreadDaemons @ Interrupted!\n");
104             }
105             finally {
106                 System.out.print("testThreadDaemons @ Thread bailing\n");
107             }
108         }
109     }
110 
testSleepZero()111     private static void testSleepZero() throws Exception {
112         Thread.currentThread().interrupt();
113         try {
114             Thread.sleep(0);
115             throw new AssertionError("unreachable");
116         } catch (InterruptedException e) {
117             if (Thread.currentThread().isInterrupted()) {
118                 throw new AssertionError("thread is interrupted");
119             }
120         }
121         System.out.print("testSleepZero finished\n");
122     }
123 
testSetName()124     private static void testSetName() throws Exception {
125         System.out.print("testSetName starting\n");
126         Thread thread = new Thread() {
127             @Override
128             public void run() {
129                 System.out.print("testSetName running\n");
130             }
131         };
132         thread.start();
133         thread.setName("HelloWorld");  // b/17302037 hang if setName called after start
134         if (!thread.getName().equals("HelloWorld")) {
135             throw new AssertionError("Unexpected thread name: " + thread.getName());
136         }
137         thread.join();
138         if (!thread.getName().equals("HelloWorld")) {
139             throw new AssertionError("Unexpected thread name after join: " + thread.getName());
140         }
141         System.out.print("testSetName finished\n");
142     }
143 
testThreadPriorities()144     private static void testThreadPriorities() throws Exception {
145         System.out.print("testThreadPriorities starting\n");
146 
147         PriorityStoringThread t1 = new PriorityStoringThread(false);
148         t1.setPriority(Thread.MAX_PRIORITY);
149         t1.start();
150         t1.join();
151         if (supportsThreadPriorities() && (t1.getNativePriority() != Thread.MAX_PRIORITY)) {
152             System.out.print("thread priority for t1 was " + t1.getNativePriority() +
153                 " [expected Thread.MAX_PRIORITY]\n");
154         }
155 
156         PriorityStoringThread t2 = new PriorityStoringThread(true);
157         t2.start();
158         t2.join();
159         if (supportsThreadPriorities() && (t2.getNativePriority() != Thread.MAX_PRIORITY)) {
160             System.out.print("thread priority for t2 was " + t2.getNativePriority() +
161                 " [expected Thread.MAX_PRIORITY]\n");
162         }
163 
164         System.out.print("testThreadPriorities finished\n");
165     }
166 
testMainThreadGroup()167     private static void testMainThreadGroup() {
168       Thread threads[] = new Thread[10];
169       Thread current = Thread.currentThread();
170       current.getThreadGroup().enumerate(threads);
171 
172       for (Thread t : threads) {
173         if (t == current) {
174           System.out.println("Found current Thread in ThreadGroup");
175           return;
176         }
177       }
178       throw new RuntimeException("Did not find main thread: " + Arrays.toString(threads));
179     }
180 
testMainThreadAllStackTraces()181     private static void testMainThreadAllStackTraces() {
182       StackTraceElement[] trace = Thread.getAllStackTraces().get(Thread.currentThread());
183       if (trace == null) {
184         throw new RuntimeException("Did not find main thread: " + Thread.getAllStackTraces());
185       }
186       List<StackTraceElement> list = Arrays.asList(trace);
187       Iterator<StackTraceElement> it = list.iterator();
188       while (it.hasNext()) {
189         StackTraceElement ste = it.next();
190         if (ste.getClassName().equals("Main")) {
191           if (!ste.getMethodName().equals("testMainThreadAllStackTraces")) {
192             throw new RuntimeException(list.toString());
193           }
194 
195           StackTraceElement ste2 = it.next();
196           if (!ste2.getClassName().equals("Main")) {
197             throw new RuntimeException(list.toString());
198           }
199           if (!ste2.getMethodName().equals("main")) {
200             throw new RuntimeException(list.toString());
201           }
202 
203           System.out.println("Found expected stack in getAllStackTraces()");
204           return;
205         }
206       }
207       throw new RuntimeException(list.toString());
208     }
209 
getNativePriority()210     private static native int getNativePriority();
supportsThreadPriorities()211     private static native boolean supportsThreadPriorities();
212 
213     static class PriorityStoringThread extends Thread {
214         private final boolean setPriority;
215         private volatile int nativePriority;
216 
PriorityStoringThread(boolean setPriority)217         public PriorityStoringThread(boolean setPriority) {
218             this.setPriority = setPriority;
219             this.nativePriority = -1;
220         }
221 
222         @Override
run()223         public void run() {
224             if (setPriority) {
225                 setPriority(Thread.MAX_PRIORITY);
226             }
227 
228             nativePriority = Main.getNativePriority();
229         }
230 
getNativePriority()231         public int getNativePriority() {
232             return nativePriority;
233         }
234     }
235 }
236