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