xref: /aosp_15_r20/art/test/088-monitor-verification/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.InvocationTargetException;
18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
19*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Modifier;
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker /*
22*795d594fSAndroid Build Coastguard Worker  * Entry point and tests that are expected to succeed.
23*795d594fSAndroid Build Coastguard Worker  */
24*795d594fSAndroid Build Coastguard Worker public class Main {
25*795d594fSAndroid Build Coastguard Worker     /**
26*795d594fSAndroid Build Coastguard Worker      * Drives tests.
27*795d594fSAndroid Build Coastguard Worker      */
main(String[] args)28*795d594fSAndroid Build Coastguard Worker     public static void main(String[] args) throws Exception {
29*795d594fSAndroid Build Coastguard Worker         System.loadLibrary(args[0]);
30*795d594fSAndroid Build Coastguard Worker         if (!hasOatFile() || runtimeIsSoftFail() || isInterpreted()) {
31*795d594fSAndroid Build Coastguard Worker             // Some tests ensure that the verifier was able to guarantee balanced locking by
32*795d594fSAndroid Build Coastguard Worker             // asserting that the test function is running as compiled code. But skip this now,
33*795d594fSAndroid Build Coastguard Worker             // as this seems to be a non-compiled code test configuration.
34*795d594fSAndroid Build Coastguard Worker             disableStackFrameAsserts();
35*795d594fSAndroid Build Coastguard Worker         }
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Main.class, "recursiveSync");
38*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Main.class, "nestedMayThrow");
39*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Main.class, "constantLock");
40*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Main.class, "notExcessiveNesting");
41*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Main.class, "notNested");
42*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(TwoPath.class, "twoPath");
43*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Class.forName("OK"), "runNoMonitors");
44*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Class.forName("OK"), "runStraightLine");
45*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Class.forName("OK"), "runBalancedJoin");
46*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Class.forName("NullLocks"), "run");
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker         Main m = new Main();
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker         m.recursiveSync(0);
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker         m.nestedMayThrow(false);
53*795d594fSAndroid Build Coastguard Worker         try {
54*795d594fSAndroid Build Coastguard Worker             m.nestedMayThrow(true);
55*795d594fSAndroid Build Coastguard Worker             System.out.println("nestedThrow(true) did not throw");
56*795d594fSAndroid Build Coastguard Worker         } catch (MyException me) {}
57*795d594fSAndroid Build Coastguard Worker         System.out.println("nestedMayThrow ok");
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker         m.constantLock();
60*795d594fSAndroid Build Coastguard Worker         System.out.println("constantLock ok");
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker         m.notExcessiveNesting();
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker         m.notNested();
65*795d594fSAndroid Build Coastguard Worker         System.out.println("notNested ok");
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker         Object obj1 = new Object();
68*795d594fSAndroid Build Coastguard Worker         Object obj2 = new Object();
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker         TwoPath.twoPath(obj1, obj2, 0);
71*795d594fSAndroid Build Coastguard Worker         System.out.println("twoPath ok");
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker         m.triplet(obj1, obj2, 0);
74*795d594fSAndroid Build Coastguard Worker         System.out.println("triplet ok");
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker         runSmaliTests();
77*795d594fSAndroid Build Coastguard Worker     }
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker     /**
80*795d594fSAndroid Build Coastguard Worker      * Recursive synchronized method.
81*795d594fSAndroid Build Coastguard Worker      */
recursiveSync(int iter)82*795d594fSAndroid Build Coastguard Worker     synchronized void recursiveSync(int iter) {
83*795d594fSAndroid Build Coastguard Worker         assertIsManaged();
84*795d594fSAndroid Build Coastguard Worker         if (iter < 40) {
85*795d594fSAndroid Build Coastguard Worker             recursiveSync(iter+1);
86*795d594fSAndroid Build Coastguard Worker         } else {
87*795d594fSAndroid Build Coastguard Worker             System.out.println("recursiveSync ok");
88*795d594fSAndroid Build Coastguard Worker         }
89*795d594fSAndroid Build Coastguard Worker     }
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker     /**
92*795d594fSAndroid Build Coastguard Worker      * Tests simple nesting, with and without a throw.
93*795d594fSAndroid Build Coastguard Worker      */
nestedMayThrow(boolean doThrow)94*795d594fSAndroid Build Coastguard Worker     void nestedMayThrow(boolean doThrow) {
95*795d594fSAndroid Build Coastguard Worker         assertIsManaged();
96*795d594fSAndroid Build Coastguard Worker         synchronized (this) {
97*795d594fSAndroid Build Coastguard Worker             synchronized (Main.class) {
98*795d594fSAndroid Build Coastguard Worker                 synchronized (new Object()) {
99*795d594fSAndroid Build Coastguard Worker                     synchronized(Class.class) {
100*795d594fSAndroid Build Coastguard Worker                         if (doThrow) {
101*795d594fSAndroid Build Coastguard Worker                             throw new MyException();
102*795d594fSAndroid Build Coastguard Worker                         }
103*795d594fSAndroid Build Coastguard Worker                     }
104*795d594fSAndroid Build Coastguard Worker                 }
105*795d594fSAndroid Build Coastguard Worker             }
106*795d594fSAndroid Build Coastguard Worker         }
107*795d594fSAndroid Build Coastguard Worker     }
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker     /**
110*795d594fSAndroid Build Coastguard Worker      * Exercises bug 3215458.
111*795d594fSAndroid Build Coastguard Worker      */
constantLock()112*795d594fSAndroid Build Coastguard Worker     void constantLock() {
113*795d594fSAndroid Build Coastguard Worker         assertIsManaged();
114*795d594fSAndroid Build Coastguard Worker         Class<?> thing = Thread.class;
115*795d594fSAndroid Build Coastguard Worker         synchronized (Thread.class) {}
116*795d594fSAndroid Build Coastguard Worker     }
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker     /**
119*795d594fSAndroid Build Coastguard Worker      * Confirms that we can have 32 nested monitors on one method.
120*795d594fSAndroid Build Coastguard Worker      */
notExcessiveNesting()121*795d594fSAndroid Build Coastguard Worker     void notExcessiveNesting() {
122*795d594fSAndroid Build Coastguard Worker         // clang-format off
123*795d594fSAndroid Build Coastguard Worker         assertIsManaged();
124*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 1
125*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 2
126*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 3
127*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 4
128*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 5
129*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 6
130*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 7
131*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 8
132*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 9
133*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 10
134*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 11
135*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 12
136*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 13
137*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 14
138*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 15
139*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 16
140*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 17
141*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 18
142*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 19
143*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 20
144*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 21
145*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 22
146*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 23
147*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 24
148*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 25
149*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 26
150*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 27
151*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 28
152*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 29
153*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 30
154*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 31
155*795d594fSAndroid Build Coastguard Worker         synchronized (this) {   // 32
156*795d594fSAndroid Build Coastguard Worker         }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
157*795d594fSAndroid Build Coastguard Worker         // clang-format on
158*795d594fSAndroid Build Coastguard Worker     }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker     /**
161*795d594fSAndroid Build Coastguard Worker      * Confirms that we can have more than 32 non-nested monitors in one
162*795d594fSAndroid Build Coastguard Worker      * method.
163*795d594fSAndroid Build Coastguard Worker      */
notNested()164*795d594fSAndroid Build Coastguard Worker     void notNested() {
165*795d594fSAndroid Build Coastguard Worker         // clang-format off
166*795d594fSAndroid Build Coastguard Worker         assertIsManaged();
167*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 1
168*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 2
169*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 3
170*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 4
171*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 5
172*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 6
173*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 7
174*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 8
175*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 9
176*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 10
177*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 11
178*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 12
179*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 13
180*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 14
181*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 15
182*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 16
183*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 17
184*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 18
185*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 19
186*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 20
187*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 21
188*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 22
189*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 23
190*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 24
191*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 25
192*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 26
193*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 27
194*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 28
195*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 29
196*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 30
197*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 31
198*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 32
199*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 33
200*795d594fSAndroid Build Coastguard Worker         synchronized (this) {}  // 34
201*795d594fSAndroid Build Coastguard Worker         // clang-format on
202*795d594fSAndroid Build Coastguard Worker     }
203*795d594fSAndroid Build Coastguard Worker 
204*795d594fSAndroid Build Coastguard Worker     /* does nothing but ensure that the compiler doesn't discard an object */
doNothing(Object obj)205*795d594fSAndroid Build Coastguard Worker     private void doNothing(Object obj) {}
206*795d594fSAndroid Build Coastguard Worker 
207*795d594fSAndroid Build Coastguard Worker     /**
208*795d594fSAndroid Build Coastguard Worker      * Lock the monitor two or three times, and make use of the locked or
209*795d594fSAndroid Build Coastguard Worker      * unlocked object.
210*795d594fSAndroid Build Coastguard Worker      */
triplet(Object obj1, Object obj2, int x)211*795d594fSAndroid Build Coastguard Worker     public void triplet(Object obj1, Object obj2, int x) {
212*795d594fSAndroid Build Coastguard Worker         Object localObj;
213*795d594fSAndroid Build Coastguard Worker 
214*795d594fSAndroid Build Coastguard Worker         synchronized (obj1) {
215*795d594fSAndroid Build Coastguard Worker             synchronized(obj1) {
216*795d594fSAndroid Build Coastguard Worker                 if (x == 0) {
217*795d594fSAndroid Build Coastguard Worker                     synchronized(obj1) {
218*795d594fSAndroid Build Coastguard Worker                         localObj = obj2;
219*795d594fSAndroid Build Coastguard Worker                     }
220*795d594fSAndroid Build Coastguard Worker                 } else {
221*795d594fSAndroid Build Coastguard Worker                     localObj = obj1;
222*795d594fSAndroid Build Coastguard Worker                 }
223*795d594fSAndroid Build Coastguard Worker             }
224*795d594fSAndroid Build Coastguard Worker         }
225*795d594fSAndroid Build Coastguard Worker 
226*795d594fSAndroid Build Coastguard Worker         doNothing(localObj);
227*795d594fSAndroid Build Coastguard Worker     }
228*795d594fSAndroid Build Coastguard Worker 
229*795d594fSAndroid Build Coastguard Worker     // Smali testing code.
runSmaliTests()230*795d594fSAndroid Build Coastguard Worker     private static void runSmaliTests() {
231*795d594fSAndroid Build Coastguard Worker         runTest("OK", new Object[] { new Object(), new Object() }, null);
232*795d594fSAndroid Build Coastguard Worker         runTest("TooDeep", new Object[] { new Object() }, null);
233*795d594fSAndroid Build Coastguard Worker         runTest("NotStructuredOverUnlock", new Object[] { new Object() },
234*795d594fSAndroid Build Coastguard Worker                 IllegalMonitorStateException.class);
235*795d594fSAndroid Build Coastguard Worker         runTest("NotStructuredUnderUnlock", new Object[] { new Object() },
236*795d594fSAndroid Build Coastguard Worker                 IllegalMonitorStateException.class);
237*795d594fSAndroid Build Coastguard Worker         runTest("UnbalancedJoin", new Object[] { new Object(), new Object() }, null);
238*795d594fSAndroid Build Coastguard Worker         runTest("UnbalancedStraight", new Object[] { new Object(), new Object() }, null);
239*795d594fSAndroid Build Coastguard Worker         runTest("NullLocks", new Object[] { false }, null);
240*795d594fSAndroid Build Coastguard Worker         runTest("NullLocks", new Object[] { true }, NullPointerException.class);
241*795d594fSAndroid Build Coastguard Worker     }
242*795d594fSAndroid Build Coastguard Worker 
runTest(String className, Object[] parameters, Class<?> excType)243*795d594fSAndroid Build Coastguard Worker     private static void runTest(String className, Object[] parameters, Class<?> excType) {
244*795d594fSAndroid Build Coastguard Worker         try {
245*795d594fSAndroid Build Coastguard Worker             Class<?> c = Class.forName(className);
246*795d594fSAndroid Build Coastguard Worker 
247*795d594fSAndroid Build Coastguard Worker             Method[] methods = c.getDeclaredMethods();
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker             // For simplicity we assume that test methods are not overloaded. So searching by name
250*795d594fSAndroid Build Coastguard Worker             // will give us the method we need to run.
251*795d594fSAndroid Build Coastguard Worker             Method method = null;
252*795d594fSAndroid Build Coastguard Worker             for (Method m : methods) {
253*795d594fSAndroid Build Coastguard Worker                 if (m.getName().equals("run")) {
254*795d594fSAndroid Build Coastguard Worker                     method = m;
255*795d594fSAndroid Build Coastguard Worker                     break;
256*795d594fSAndroid Build Coastguard Worker                 }
257*795d594fSAndroid Build Coastguard Worker             }
258*795d594fSAndroid Build Coastguard Worker 
259*795d594fSAndroid Build Coastguard Worker             if (method == null) {
260*795d594fSAndroid Build Coastguard Worker                 System.out.println("Could not find test method for " + className);
261*795d594fSAndroid Build Coastguard Worker             } else if (!Modifier.isStatic(method.getModifiers())) {
262*795d594fSAndroid Build Coastguard Worker                 System.out.println("Test method for " + className + " is not static.");
263*795d594fSAndroid Build Coastguard Worker             } else {
264*795d594fSAndroid Build Coastguard Worker                 method.invoke(null, parameters);
265*795d594fSAndroid Build Coastguard Worker                 if (excType != null) {
266*795d594fSAndroid Build Coastguard Worker                     System.out.println("Expected an exception in " + className);
267*795d594fSAndroid Build Coastguard Worker                 }
268*795d594fSAndroid Build Coastguard Worker             }
269*795d594fSAndroid Build Coastguard Worker         } catch (Throwable exc) {
270*795d594fSAndroid Build Coastguard Worker             if (excType == null) {
271*795d594fSAndroid Build Coastguard Worker                 System.out.println("Did not expect exception " + exc + " for " + className);
272*795d594fSAndroid Build Coastguard Worker                 exc.printStackTrace(System.out);
273*795d594fSAndroid Build Coastguard Worker             } else if (exc instanceof InvocationTargetException && exc.getCause() != null &&
274*795d594fSAndroid Build Coastguard Worker                        exc.getCause().getClass().equals(excType)) {
275*795d594fSAndroid Build Coastguard Worker                 // Expected exception is wrapped in InvocationTargetException.
276*795d594fSAndroid Build Coastguard Worker             } else if (!excType.equals(exc.getClass())) {
277*795d594fSAndroid Build Coastguard Worker                 System.out.println("Expected " + excType.getName() + ", but got " + exc.getClass());
278*795d594fSAndroid Build Coastguard Worker             } else {
279*795d594fSAndroid Build Coastguard Worker               // Expected exception, do nothing.
280*795d594fSAndroid Build Coastguard Worker             }
281*795d594fSAndroid Build Coastguard Worker         }
282*795d594fSAndroid Build Coastguard Worker     }
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker     // Helpers for the smali code.
assertIsInterpreted()285*795d594fSAndroid Build Coastguard Worker     public static native void assertIsInterpreted();
assertIsManaged()286*795d594fSAndroid Build Coastguard Worker     public static native void assertIsManaged();
hasOatFile()287*795d594fSAndroid Build Coastguard Worker     public static native boolean hasOatFile();
runtimeIsSoftFail()288*795d594fSAndroid Build Coastguard Worker     public static native boolean runtimeIsSoftFail();
isInterpreted()289*795d594fSAndroid Build Coastguard Worker     public static native boolean isInterpreted();
disableStackFrameAsserts()290*795d594fSAndroid Build Coastguard Worker     public static native void disableStackFrameAsserts();
ensureJitCompiled(Class<?> itf, String method_name)291*795d594fSAndroid Build Coastguard Worker     private static native void ensureJitCompiled(Class<?> itf, String method_name);
292*795d594fSAndroid Build Coastguard Worker }
293