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
17import java.util.ArrayList;
18
19/**
20 * Test some basic thread stuff.
21 */
22public class Main {
23    public static void main(String[] args) throws Exception {
24        System.loadLibrary(args[0]);
25        System.out.println("thread test starting");
26        testThreadCapacity();
27        testThreadDaemons();
28        testSleepZero();
29        testSetName();
30        testThreadPriorities();
31        System.out.println("thread test done");
32    }
33
34    /*
35     * Simple thread capacity test.
36     */
37    private static void testThreadCapacity() throws Exception {
38        TestCapacityThread[] threads = new TestCapacityThread[512];
39        for (int i = 0; i < 512; i++) {
40            threads[i] = new TestCapacityThread();
41        }
42
43        for (TestCapacityThread thread : threads) {
44            thread.start();
45        }
46        for (TestCapacityThread thread : threads) {
47            thread.join();
48        }
49
50        System.out.println("testThreadCapacity thread count: " + TestCapacityThread.mCount);
51    }
52
53    private static class TestCapacityThread extends Thread {
54        static int mCount = 0;
55        public void run() {
56            synchronized (TestCapacityThread.class) {
57                ++mCount;
58            }
59            try {
60                sleep(1000);
61            } catch (Exception ex) {
62            }
63        }
64    }
65
66    private static void testThreadDaemons() {
67        Thread t = new Thread(null, new TestDaemonThread(), "TestDaemonThread", 7168);
68
69        t.setDaemon(false);
70
71        System.out.print("testThreadDaemons starting thread '" + t.getName() + "'\n");
72        t.start();
73
74        try {
75            t.join();
76        } catch (InterruptedException ex) {
77            ex.printStackTrace();
78        }
79
80        System.out.print("testThreadDaemons finished\n");
81    }
82
83    private static class TestDaemonThread implements Runnable {
84        public void run() {
85            System.out.print("testThreadDaemons @ Thread running\n");
86
87            try {
88                Thread.currentThread().setDaemon(true);
89                System.out.print("testThreadDaemons @ FAILED: setDaemon() succeeded\n");
90            } catch (IllegalThreadStateException itse) {
91                System.out.print("testThreadDaemons @ Got expected setDaemon exception\n");
92            }
93
94            try {
95                Thread.sleep(2000);
96            }
97            catch (InterruptedException ie) {
98                System.out.print("testThreadDaemons @ Interrupted!\n");
99            }
100            finally {
101                System.out.print("testThreadDaemons @ Thread bailing\n");
102            }
103        }
104    }
105
106    private static void testSleepZero() throws Exception {
107        Thread.currentThread().interrupt();
108        try {
109            Thread.sleep(0);
110            throw new AssertionError("unreachable");
111        } catch (InterruptedException e) {
112            if (Thread.currentThread().isInterrupted()) {
113                throw new AssertionError("thread is interrupted");
114            }
115        }
116        System.out.print("testSleepZero finished\n");
117    }
118
119    private static void testSetName() throws Exception {
120        System.out.print("testSetName starting\n");
121        Thread thread = new Thread() {
122            @Override
123            public void run() {
124                System.out.print("testSetName running\n");
125            }
126        };
127        thread.start();
128        thread.setName("HelloWorld");  // b/17302037 hang if setName called after start
129        if (!thread.getName().equals("HelloWorld")) {
130            throw new AssertionError("Unexpected thread name: " + thread.getName());
131        }
132        thread.join();
133        if (!thread.getName().equals("HelloWorld")) {
134            throw new AssertionError("Unexpected thread name after join: " + thread.getName());
135        }
136        System.out.print("testSetName finished\n");
137    }
138
139    private static void testThreadPriorities() throws Exception {
140        System.out.print("testThreadPriorities starting\n");
141
142        PriorityStoringThread t1 = new PriorityStoringThread(false);
143        t1.setPriority(Thread.MAX_PRIORITY);
144        t1.start();
145        t1.join();
146        if (supportsThreadPriorities() && (t1.getNativePriority() != Thread.MAX_PRIORITY)) {
147            System.out.print("thread priority for t1 was " + t1.getNativePriority() +
148                " [expected Thread.MAX_PRIORITY]\n");
149        }
150
151        PriorityStoringThread t2 = new PriorityStoringThread(true);
152        t2.start();
153        t2.join();
154        if (supportsThreadPriorities() && (t2.getNativePriority() != Thread.MAX_PRIORITY)) {
155            System.out.print("thread priority for t2 was " + t2.getNativePriority() +
156                " [expected Thread.MAX_PRIORITY]\n");
157        }
158
159        System.out.print("testThreadPriorities finished\n");
160    }
161
162    private static native int getNativePriority();
163    private static native boolean supportsThreadPriorities();
164
165    static class PriorityStoringThread extends Thread {
166        private final boolean setPriority;
167        private volatile int nativePriority;
168
169        public PriorityStoringThread(boolean setPriority) {
170            this.setPriority = setPriority;
171            this.nativePriority = -1;
172        }
173
174        @Override
175        public void run() {
176            if (setPriority) {
177                setPriority(Thread.MAX_PRIORITY);
178            }
179
180            nativePriority = Main.getNativePriority();
181        }
182
183        public int getNativePriority() {
184            return nativePriority;
185        }
186    }
187}
188