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