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