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