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 assertIsManaged(); 123 synchronized (this) { // 1 124 synchronized (this) { // 2 125 synchronized (this) { // 3 126 synchronized (this) { // 4 127 synchronized (this) { // 5 128 synchronized (this) { // 6 129 synchronized (this) { // 7 130 synchronized (this) { // 8 131 synchronized (this) { // 9 132 synchronized (this) { // 10 133 synchronized (this) { // 11 134 synchronized (this) { // 12 135 synchronized (this) { // 13 136 synchronized (this) { // 14 137 synchronized (this) { // 15 138 synchronized (this) { // 16 139 synchronized (this) { // 17 140 synchronized (this) { // 18 141 synchronized (this) { // 19 142 synchronized (this) { // 20 143 synchronized (this) { // 21 144 synchronized (this) { // 22 145 synchronized (this) { // 23 146 synchronized (this) { // 24 147 synchronized (this) { // 25 148 synchronized (this) { // 26 149 synchronized (this) { // 27 150 synchronized (this) { // 28 151 synchronized (this) { // 29 152 synchronized (this) { // 30 153 synchronized (this) { // 31 154 synchronized (this) { // 32 155 }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} 156 } 157 158 /** 159 * Confirms that we can have more than 32 non-nested monitors in one 160 * method. 161 */ notNested()162 void notNested() { 163 assertIsManaged(); 164 synchronized (this) {} // 1 165 synchronized (this) {} // 2 166 synchronized (this) {} // 3 167 synchronized (this) {} // 4 168 synchronized (this) {} // 5 169 synchronized (this) {} // 6 170 synchronized (this) {} // 7 171 synchronized (this) {} // 8 172 synchronized (this) {} // 9 173 synchronized (this) {} // 10 174 synchronized (this) {} // 11 175 synchronized (this) {} // 12 176 synchronized (this) {} // 13 177 synchronized (this) {} // 14 178 synchronized (this) {} // 15 179 synchronized (this) {} // 16 180 synchronized (this) {} // 17 181 synchronized (this) {} // 18 182 synchronized (this) {} // 19 183 synchronized (this) {} // 20 184 synchronized (this) {} // 21 185 synchronized (this) {} // 22 186 synchronized (this) {} // 23 187 synchronized (this) {} // 24 188 synchronized (this) {} // 25 189 synchronized (this) {} // 26 190 synchronized (this) {} // 27 191 synchronized (this) {} // 28 192 synchronized (this) {} // 29 193 synchronized (this) {} // 30 194 synchronized (this) {} // 31 195 synchronized (this) {} // 32 196 synchronized (this) {} // 33 197 synchronized (this) {} // 34 198 } 199 200 /* does nothing but ensure that the compiler doesn't discard an object */ doNothing(Object obj)201 private void doNothing(Object obj) {} 202 203 /** 204 * Lock the monitor two or three times, and make use of the locked or 205 * unlocked object. 206 */ triplet(Object obj1, Object obj2, int x)207 public void triplet(Object obj1, Object obj2, int x) { 208 Object localObj; 209 210 synchronized (obj1) { 211 synchronized(obj1) { 212 if (x == 0) { 213 synchronized(obj1) { 214 localObj = obj2; 215 } 216 } else { 217 localObj = obj1; 218 } 219 } 220 } 221 222 doNothing(localObj); 223 } 224 225 // Smali testing code. runSmaliTests()226 private static void runSmaliTests() { 227 runTest("OK", new Object[] { new Object(), new Object() }, null); 228 runTest("TooDeep", new Object[] { new Object() }, null); 229 runTest("NotStructuredOverUnlock", new Object[] { new Object() }, 230 IllegalMonitorStateException.class); 231 runTest("NotStructuredUnderUnlock", new Object[] { new Object() }, 232 IllegalMonitorStateException.class); 233 runTest("UnbalancedJoin", new Object[] { new Object(), new Object() }, null); 234 runTest("UnbalancedStraight", new Object[] { new Object(), new Object() }, null); 235 runTest("NullLocks", new Object[] { false }, null); 236 runTest("NullLocks", new Object[] { true }, NullPointerException.class); 237 } 238 runTest(String className, Object[] parameters, Class<?> excType)239 private static void runTest(String className, Object[] parameters, Class<?> excType) { 240 try { 241 Class<?> c = Class.forName(className); 242 243 Method[] methods = c.getDeclaredMethods(); 244 245 // For simplicity we assume that test methods are not overloaded. So searching by name 246 // will give us the method we need to run. 247 Method method = null; 248 for (Method m : methods) { 249 if (m.getName().equals("run")) { 250 method = m; 251 break; 252 } 253 } 254 255 if (method == null) { 256 System.out.println("Could not find test method for " + className); 257 } else if (!Modifier.isStatic(method.getModifiers())) { 258 System.out.println("Test method for " + className + " is not static."); 259 } else { 260 method.invoke(null, parameters); 261 if (excType != null) { 262 System.out.println("Expected an exception in " + className); 263 } 264 } 265 } catch (Throwable exc) { 266 if (excType == null) { 267 System.out.println("Did not expect exception " + exc + " for " + className); 268 exc.printStackTrace(System.out); 269 } else if (exc instanceof InvocationTargetException && exc.getCause() != null && 270 exc.getCause().getClass().equals(excType)) { 271 // Expected exception is wrapped in InvocationTargetException. 272 } else if (!excType.equals(exc.getClass())) { 273 System.out.println("Expected " + excType.getName() + ", but got " + exc.getClass()); 274 } else { 275 // Expected exception, do nothing. 276 } 277 } 278 } 279 280 // Helpers for the smali code. assertIsInterpreted()281 public static native void assertIsInterpreted(); assertIsManaged()282 public static native void assertIsManaged(); hasOatFile()283 public static native boolean hasOatFile(); runtimeIsSoftFail()284 public static native boolean runtimeIsSoftFail(); isInterpreted()285 public static native boolean isInterpreted(); disableStackFrameAsserts()286 public static native void disableStackFrameAsserts(); ensureJitCompiled(Class<?> itf, String method_name)287 private static native void ensureJitCompiled(Class<?> itf, String method_name); 288 } 289