1/*
2 * Copyright (C) 2010 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
18/*
19 * Entry point and tests that are expected to succeed.
20 */
21public class Main {
22    /**
23     * Drives tests.
24     */
25    public static void main(String[] args) {
26        Main m = new Main();
27
28        m.recursiveSync(0);
29
30        m.nestedMayThrow(false);
31        try {
32            m.nestedMayThrow(true);
33            System.err.println("nestedThrow(true) did not throw");
34        } catch (MyException me) {}
35        System.out.println("nestedMayThrow ok");
36
37        m.constantLock();
38        System.out.println("constantLock ok");
39
40        m.notExcessiveNesting();
41        if (false) {    // TODO: remove when verification is turned on
42        try {
43            TooDeep.excessiveNesting();
44            System.err.println("excessiveNesting did not throw");
45        } catch (VerifyError ve) {}
46        }
47        System.out.println("excessiveNesting ok");
48
49        m.notNested();
50        System.out.println("notNested ok");
51
52        Object obj1 = new Object();
53        Object obj2 = new Object();
54
55        m.twoPath(obj1, obj2, 0);
56        System.out.println("twoPath ok");
57
58        m.triplet(obj1, obj2, 0);
59        System.out.println("triplet ok");
60    }
61
62    /**
63     * Recursive synchronized method.
64     */
65    synchronized void recursiveSync(int iter) {
66        if (iter < 40) {
67            recursiveSync(iter+1);
68        } else {
69            System.out.println("recursiveSync ok");
70        }
71    }
72
73    /**
74     * Tests simple nesting, with and without a throw.
75     */
76    void nestedMayThrow(boolean doThrow) {
77        synchronized (this) {
78            synchronized (Main.class) {
79                synchronized (new Object()) {
80                    synchronized(Class.class) {
81                        if (doThrow) {
82                            throw new MyException();
83                        }
84                    }
85                }
86            }
87        }
88    }
89
90    /**
91     * Exercises bug 3215458.
92     */
93    void constantLock() {
94        Class thing = Thread.class;
95        synchronized (Thread.class) {}
96    }
97
98    /**
99     * Confirms that we can have 32 nested monitors on one method.
100     */
101    void notExcessiveNesting() {
102        synchronized (this) {   // 1
103        synchronized (this) {   // 2
104        synchronized (this) {   // 3
105        synchronized (this) {   // 4
106        synchronized (this) {   // 5
107        synchronized (this) {   // 6
108        synchronized (this) {   // 7
109        synchronized (this) {   // 8
110        synchronized (this) {   // 9
111        synchronized (this) {   // 10
112        synchronized (this) {   // 11
113        synchronized (this) {   // 12
114        synchronized (this) {   // 13
115        synchronized (this) {   // 14
116        synchronized (this) {   // 15
117        synchronized (this) {   // 16
118        synchronized (this) {   // 17
119        synchronized (this) {   // 18
120        synchronized (this) {   // 19
121        synchronized (this) {   // 20
122        synchronized (this) {   // 21
123        synchronized (this) {   // 22
124        synchronized (this) {   // 23
125        synchronized (this) {   // 24
126        synchronized (this) {   // 25
127        synchronized (this) {   // 26
128        synchronized (this) {   // 27
129        synchronized (this) {   // 28
130        synchronized (this) {   // 29
131        synchronized (this) {   // 30
132        synchronized (this) {   // 31
133        synchronized (this) {   // 32
134        }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
135    }
136
137    /**
138     * Confirms that we can have more than 32 non-nested monitors in one
139     * method.
140     */
141    void notNested() {
142        synchronized (this) {}  // 1
143        synchronized (this) {}  // 2
144        synchronized (this) {}  // 3
145        synchronized (this) {}  // 4
146        synchronized (this) {}  // 5
147        synchronized (this) {}  // 6
148        synchronized (this) {}  // 7
149        synchronized (this) {}  // 8
150        synchronized (this) {}  // 9
151        synchronized (this) {}  // 10
152        synchronized (this) {}  // 11
153        synchronized (this) {}  // 12
154        synchronized (this) {}  // 13
155        synchronized (this) {}  // 14
156        synchronized (this) {}  // 15
157        synchronized (this) {}  // 16
158        synchronized (this) {}  // 17
159        synchronized (this) {}  // 18
160        synchronized (this) {}  // 19
161        synchronized (this) {}  // 20
162        synchronized (this) {}  // 21
163        synchronized (this) {}  // 22
164        synchronized (this) {}  // 23
165        synchronized (this) {}  // 24
166        synchronized (this) {}  // 25
167        synchronized (this) {}  // 26
168        synchronized (this) {}  // 27
169        synchronized (this) {}  // 28
170        synchronized (this) {}  // 29
171        synchronized (this) {}  // 30
172        synchronized (this) {}  // 31
173        synchronized (this) {}  // 32
174        synchronized (this) {}  // 33
175        synchronized (this) {}  // 34
176    }
177
178    /* does nothing but ensure that the compiler doesn't discard an object */
179    private void doNothing(Object obj) {}
180
181    /**
182     * Conditionally uses one of the synchronized objects.
183     */
184    public void twoPath(Object obj1, Object obj2, int x) {
185        Object localObj;
186
187        synchronized (obj1) {
188            synchronized(obj2) {
189                if (x == 0) {
190                    localObj = obj2;
191                } else {
192                    localObj = obj1;
193                }
194            }
195        }
196
197        doNothing(localObj);
198    }
199
200    /**
201     * Lock the monitor two or three times, and make use of the locked or
202     * unlocked object.
203     */
204    public void triplet(Object obj1, Object obj2, int x) {
205        Object localObj;
206
207        synchronized (obj1) {
208            synchronized(obj1) {
209                if (x == 0) {
210                    synchronized(obj1) {
211                        localObj = obj2;
212                    }
213                } else {
214                    localObj = obj1;
215                }
216            }
217        }
218
219        doNothing(localObj);
220    }
221}
222